upd(crm): refactor crm service layer
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package repository
|
||||
|
||||
const (
|
||||
// @todo root should be configurable
|
||||
// @todo move this to db or stack it inside the binary or container
|
||||
fieldPath = "crm/data/%s.json"
|
||||
)
|
||||
+34
-21
@@ -10,27 +10,40 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
// @todo root should be configurable
|
||||
// @todo move this to db or stack it inside the binary or container
|
||||
fieldPath = "crm/data/%s.json"
|
||||
)
|
||||
|
||||
type (
|
||||
field struct{}
|
||||
Field interface {
|
||||
With(ctx context.Context) Field
|
||||
|
||||
FindByName(name string) (*types.Field, error)
|
||||
Find() ([]*types.Field, error)
|
||||
}
|
||||
|
||||
field struct {
|
||||
*repository
|
||||
}
|
||||
)
|
||||
|
||||
func Field() field {
|
||||
return field{}
|
||||
func NewField(ctx context.Context) Field {
|
||||
return &field{
|
||||
repository: &repository{
|
||||
ctx: ctx,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *field) With(ctx context.Context) Field {
|
||||
return &field{
|
||||
repository: r.repository.With(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// Finds field by it's name and returns it
|
||||
func (repo field) FindByName(ctx context.Context, name string) (*types.Field, error) {
|
||||
return repo.decode(fmt.Sprintf(fieldPath, name))
|
||||
func (f *field) FindByName(name string) (*types.Field, error) {
|
||||
return f.fieldDecode(fmt.Sprintf(fieldPath, name))
|
||||
}
|
||||
|
||||
// Returns all known fields
|
||||
func (repo field) Find(ctx context.Context) ([]*types.Field, error) {
|
||||
func (f *field) Find() ([]*types.Field, error) {
|
||||
matches, err := filepath.Glob(fmt.Sprintf(fieldPath, "*"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -38,14 +51,14 @@ func (repo field) Find(ctx context.Context) ([]*types.Field, error) {
|
||||
|
||||
res := make([]*types.Field, len(matches))
|
||||
for i, match := range matches {
|
||||
if res[i], err = repo.decode(match); err != nil {
|
||||
if res[i], err = f.fieldDecode(match); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (repo field) decode(filepath string) (*types.Field, error) {
|
||||
func (f *field) fieldDecode(filepath string) (*types.Field, error) {
|
||||
file, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
// @todo wrap error
|
||||
@@ -54,9 +67,15 @@ func (repo field) decode(filepath string) (*types.Field, error) {
|
||||
|
||||
defer file.Close()
|
||||
|
||||
// Removes path and extension from full filename
|
||||
fieldTypeFromPath := func(filepath string) string {
|
||||
t := path.Base(filepath)
|
||||
return t[:len(t)-5]
|
||||
}
|
||||
|
||||
// Preset field's type with name of the file (sans .json)
|
||||
// if type is explicitly set within the file, it will be overwritten
|
||||
field := &types.Field{Type: repo.typeFromPath(filepath)}
|
||||
field := &types.Field{Type: fieldTypeFromPath(filepath)}
|
||||
if err := json.NewDecoder(file).Decode(&field); err != nil {
|
||||
// @todo wrap error
|
||||
return nil, err
|
||||
@@ -64,9 +83,3 @@ func (repo field) decode(filepath string) (*types.Field, error) {
|
||||
|
||||
return field, nil
|
||||
}
|
||||
|
||||
// Removes path and extension from full filename
|
||||
func (repo field) typeFromPath(filepath string) string {
|
||||
t := path.Base(filepath)
|
||||
return t[:len(t)-5]
|
||||
}
|
||||
|
||||
+40
-20
@@ -7,17 +7,39 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
module struct{}
|
||||
Module interface {
|
||||
With(ctx context.Context) Module
|
||||
|
||||
FindByID(id uint64) (*types.Module, error)
|
||||
Find() ([]*types.Module, error)
|
||||
Create(mod *types.Module) (*types.Module, error)
|
||||
Update(mod *types.Module) (*types.Module, error)
|
||||
DeleteByID(id uint64) error
|
||||
}
|
||||
|
||||
module struct {
|
||||
*repository
|
||||
}
|
||||
)
|
||||
|
||||
func Module() module {
|
||||
return module{}
|
||||
func NewModule(ctx context.Context) Module {
|
||||
return &module{
|
||||
repository: &repository{
|
||||
ctx: ctx,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r module) FindByID(ctx context.Context, id uint64) (*types.Module, error) {
|
||||
db := factory.Database.MustGet()
|
||||
func (r *module) With(ctx context.Context) Module {
|
||||
return &module{
|
||||
repository: r.repository.With(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (r *module) FindByID(id uint64) (*types.Module, error) {
|
||||
mod := &types.Module{}
|
||||
if err := db.Get(mod, "SELECT * FROM crm_module WHERE id = ?", id); err != nil {
|
||||
if err := r.db().Get(mod, "SELECT * FROM crm_module WHERE id = ?", id); err != nil {
|
||||
println(err.Error())
|
||||
return nil, ErrDatabaseError
|
||||
} else {
|
||||
@@ -25,10 +47,9 @@ func (r module) FindByID(ctx context.Context, id uint64) (*types.Module, error)
|
||||
}
|
||||
}
|
||||
|
||||
func (r module) Find(ctx context.Context) ([]*types.Module, error) {
|
||||
db := factory.Database.MustGet()
|
||||
func (r *module) Find() ([]*types.Module, error) {
|
||||
mod := make([]*types.Module, 0)
|
||||
if err := db.With(ctx).Select(&mod, "SELECT * FROM crm_module ORDER BY name ASC"); err != nil {
|
||||
if err := r.db().Select(&mod, "SELECT * FROM crm_module ORDER BY name ASC"); err != nil {
|
||||
println(err.Error())
|
||||
return nil, ErrDatabaseError
|
||||
} else {
|
||||
@@ -36,26 +57,25 @@ func (r module) Find(ctx context.Context) ([]*types.Module, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r module) Create(ctx context.Context, mod *types.Module) (*types.Module, error) {
|
||||
func (r *module) Create(mod *types.Module) (*types.Module, error) {
|
||||
mod.ID = factory.Sonyflake.NextID()
|
||||
return mod, factory.Database.MustGet().With(ctx).Insert("crm_module", mod)
|
||||
return mod, r.db().Insert("crm_module", mod)
|
||||
}
|
||||
|
||||
func (r module) Update(ctx context.Context, mod *types.Module) (*types.Module, error) {
|
||||
return mod, factory.Database.MustGet().With(ctx).Replace("crm_module", mod)
|
||||
func (r *module) Update(mod *types.Module) (*types.Module, error) {
|
||||
return mod, r.db().Replace("crm_module", mod)
|
||||
|
||||
}
|
||||
|
||||
func (r module) DeleteByID(ctx context.Context, id uint64) error {
|
||||
db := factory.Database.MustGet()
|
||||
if _, err := db.Exec("DELETE FROM crm_module WHERE ID = ?", id); err != nil {
|
||||
func (r *module) DeleteByID(id uint64) error {
|
||||
if _, err := r.db().Exec("DELETE FROM crm_module WHERE ID = ?", id); err != nil {
|
||||
return ErrDatabaseError
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
//func (r module) Edit(r *moduleEditRequest) (interface{}, error) {
|
||||
//func (r *module) Edit(r *moduleEditRequest) (interface{}, error) {
|
||||
// db := factory.Database.MustGet()
|
||||
// m := module{}.New()
|
||||
// m.SetID(r.id).SetName(r.name)
|
||||
@@ -66,7 +86,7 @@ func (r module) DeleteByID(ctx context.Context, id uint64) error {
|
||||
// return m, db.With(ctx).Insert("crm_module", m)
|
||||
//}
|
||||
//
|
||||
//func (r module) ContentList(r *moduleContentListRequest) (interface{}, error) {
|
||||
//func (r *module) ContentList(r *moduleContentListRequest) (interface{}, error) {
|
||||
// db := factory.Database.MustGet()
|
||||
// if r.id > 0 {
|
||||
// m := ModuleContentRow{}.New()
|
||||
@@ -78,10 +98,10 @@ func (r module) DeleteByID(ctx context.Context, id uint64) error {
|
||||
// return res, err
|
||||
//}
|
||||
//
|
||||
//func (r module) ContentEdit(r *moduleContentEditRequest) (interface{}, error) {
|
||||
//func (r *module) ContentEdit(r *moduleContentEditRequest) (interface{}, error) {
|
||||
// return nil, errors.New("Not implemented: module.content/edit")
|
||||
//}
|
||||
//
|
||||
//func (r module) ContentDelete(r *moduleContentDeleteRequest) (interface{}, error) {
|
||||
//func (r *module) ContentDelete(r *moduleContentDeleteRequest) (interface{}, error) {
|
||||
// return nil, errors.New("Not implemented: module.content/delete")
|
||||
//}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/titpetric/factory"
|
||||
)
|
||||
|
||||
type (
|
||||
repository struct {
|
||||
ctx context.Context
|
||||
|
||||
// Current transaction
|
||||
tx *factory.DB
|
||||
}
|
||||
)
|
||||
|
||||
// With updates repository and database contexts
|
||||
func (r *repository) With(ctx context.Context) *repository {
|
||||
return &repository{
|
||||
ctx: ctx,
|
||||
tx: r.db().With(r.ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *repository) Begin() error {
|
||||
return r.db().Begin()
|
||||
}
|
||||
|
||||
func (r *repository) Commit() error {
|
||||
return errors.Wrap(r.db().Commit(), "Can not commit changes")
|
||||
}
|
||||
|
||||
func (r *repository) Rollback() error {
|
||||
return errors.Wrap(r.db().Rollback(), "Can not rollback changes")
|
||||
}
|
||||
|
||||
func (r *repository) db() *factory.DB {
|
||||
if r.tx == nil {
|
||||
r.tx = factory.Database.MustGet().With(r.ctx)
|
||||
}
|
||||
return r.tx
|
||||
}
|
||||
+11
-10
@@ -6,31 +6,32 @@ import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/crm/rest/server"
|
||||
"github.com/crusttech/crust/crm/types"
|
||||
"github.com/crusttech/crust/crm/service"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
Field struct {
|
||||
svc fieldService
|
||||
field service.FieldService
|
||||
}
|
||||
|
||||
fieldService interface {
|
||||
FieldService interface {
|
||||
FindByName(ctx context.Context, name string) (*types.Field, error)
|
||||
Find(ctx context.Context) ([]*types.Field, error)
|
||||
}
|
||||
)
|
||||
|
||||
func (Field) New(fieldSvc fieldService) *Field {
|
||||
var ctrl = &Field{}
|
||||
ctrl.svc = fieldSvc
|
||||
return ctrl
|
||||
func (Field) New() server.FieldAPI {
|
||||
return &Field{
|
||||
field: service.Field(),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Field) List(ctx context.Context, _ *server.FieldListRequest) (interface{}, error) {
|
||||
return self.svc.Find(ctx)
|
||||
func (s *Field) List(ctx context.Context, _ *server.FieldListRequest) (interface{}, error) {
|
||||
return s.field.With(ctx).Find()
|
||||
}
|
||||
|
||||
func (self *Field) Type(ctx context.Context, r *server.FieldTypeRequest) (interface{}, error) {
|
||||
return self.svc.FindByName(ctx, r.ID)
|
||||
func (s *Field) Type(ctx context.Context, r *server.FieldTypeRequest) (interface{}, error) {
|
||||
return s.field.With(ctx).FindByName(r.ID)
|
||||
}
|
||||
|
||||
+16
-24
@@ -8,51 +8,43 @@ import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/crm/rest/server"
|
||||
"github.com/crusttech/crust/crm/types"
|
||||
"github.com/crusttech/crust/crm/service"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
Module struct {
|
||||
svc moduleService
|
||||
}
|
||||
|
||||
moduleService interface {
|
||||
FindByID(ctx context.Context, moduleID uint64) (*types.Module, error)
|
||||
Find(ctx context.Context) ([]*types.Module, error)
|
||||
|
||||
Create(ctx context.Context, module *types.Module) (*types.Module, error)
|
||||
Update(ctx context.Context, module *types.Module) (*types.Module, error)
|
||||
DeleteByID(ctx context.Context, moduleID uint64) error
|
||||
module service.ModuleService
|
||||
}
|
||||
)
|
||||
|
||||
func (Module) New(moduleSvc moduleService) *Module {
|
||||
var ctrl = &Module{}
|
||||
ctrl.svc = moduleSvc
|
||||
return ctrl
|
||||
func (Module) New() server.ModuleAPI {
|
||||
return &Module{
|
||||
module: service.Module(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Module) List(ctx context.Context, r *server.ModuleListRequest) (interface{}, error) {
|
||||
return c.svc.Find(ctx)
|
||||
func (s *Module) List(ctx context.Context, r *server.ModuleListRequest) (interface{}, error) {
|
||||
return s.module.With(ctx).Find()
|
||||
}
|
||||
|
||||
func (c *Module) Read(ctx context.Context, r *server.ModuleReadRequest) (interface{}, error) {
|
||||
return c.svc.FindByID(ctx, r.ID)
|
||||
func (s *Module) Read(ctx context.Context, r *server.ModuleReadRequest) (interface{}, error) {
|
||||
return s.module.With(ctx).FindByID(r.ID)
|
||||
}
|
||||
|
||||
func (c *Module) Delete(ctx context.Context, r *server.ModuleDeleteRequest) (interface{}, error) {
|
||||
return resputil.OK(), c.svc.DeleteByID(ctx, r.ID)
|
||||
func (s *Module) Delete(ctx context.Context, r *server.ModuleDeleteRequest) (interface{}, error) {
|
||||
return resputil.OK(), s.module.With(ctx).DeleteByID(r.ID)
|
||||
}
|
||||
|
||||
func (c *Module) Create(ctx context.Context, r *server.ModuleCreateRequest) (interface{}, error) {
|
||||
func (s *Module) Create(ctx context.Context, r *server.ModuleCreateRequest) (interface{}, error) {
|
||||
m := &types.Module{Name: r.Name}
|
||||
return c.svc.Create(ctx, m)
|
||||
return s.module.With(ctx).Create(m)
|
||||
}
|
||||
|
||||
func (c *Module) Edit(ctx context.Context, r *server.ModuleEditRequest) (interface{}, error) {
|
||||
func (s *Module) Edit(ctx context.Context, r *server.ModuleEditRequest) (interface{}, error) {
|
||||
m := &types.Module{ID: r.ID, Name: r.Name}
|
||||
return c.svc.Update(ctx, m)
|
||||
return s.module.With(ctx).Update(m)
|
||||
}
|
||||
|
||||
func (*Module) ContentList(ctx context.Context, r *server.ModuleContentListRequest) (interface{}, error) {
|
||||
|
||||
+2
-9
@@ -3,7 +3,6 @@ package rest
|
||||
import (
|
||||
"github.com/crusttech/crust/auth"
|
||||
"github.com/crusttech/crust/crm/rest/server"
|
||||
"github.com/crusttech/crust/crm/service"
|
||||
"github.com/go-chi/chi"
|
||||
)
|
||||
|
||||
@@ -14,12 +13,6 @@ type (
|
||||
)
|
||||
|
||||
func MountRoutes(jwtAuth authTokenEncoder) func(chi.Router) {
|
||||
// Initialize services
|
||||
var (
|
||||
fieldSvc = service.Field()
|
||||
moduleSvc = service.Module()
|
||||
)
|
||||
|
||||
// @todo pass jwtAuth to auth handlers (signUp) for JWT generation
|
||||
|
||||
// Initialize handers & controllers.
|
||||
@@ -27,11 +20,11 @@ func MountRoutes(jwtAuth authTokenEncoder) func(chi.Router) {
|
||||
r.Use(auth.AuthenticationMiddlewareValidOnly)
|
||||
|
||||
(&server.FieldHandlers{
|
||||
Field: (&Field{}).New(fieldSvc),
|
||||
Field: Field{}.New(),
|
||||
}).MountRoutes(r)
|
||||
|
||||
(&server.ModuleHandlers{
|
||||
Module: (&Module{}).New(moduleSvc),
|
||||
Module: Module{}.New(),
|
||||
}).MountRoutes(r)
|
||||
}
|
||||
}
|
||||
|
||||
+19
-12
@@ -7,26 +7,33 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
fieldType struct {
|
||||
repository fieldTypeRepository
|
||||
field struct {
|
||||
repository repository.Field
|
||||
}
|
||||
|
||||
fieldTypeRepository interface {
|
||||
FindByName(ctx context.Context, name string) (*types.Field, error)
|
||||
Find(ctx context.Context) ([]*types.Field, error)
|
||||
FieldService interface {
|
||||
With(ctx context.Context) FieldService
|
||||
FindByName(name string) (*types.Field, error)
|
||||
Find() ([]*types.Field, error)
|
||||
}
|
||||
)
|
||||
|
||||
func Field() fieldType {
|
||||
return fieldType{
|
||||
repository: repository.Field(),
|
||||
func Field() FieldService {
|
||||
return &field{
|
||||
repository: repository.NewField(context.Background()),
|
||||
}
|
||||
}
|
||||
|
||||
func (svc fieldType) FindByName(ctx context.Context, name string) (*types.Field, error) {
|
||||
return svc.repository.FindByName(ctx, name)
|
||||
func (s *field) With(ctx context.Context) FieldService {
|
||||
return &field{
|
||||
repository: s.repository.With(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (svc fieldType) Find(ctx context.Context) ([]*types.Field, error) {
|
||||
return svc.repository.Find(ctx)
|
||||
func (s *field) FindByName(name string) (*types.Field, error) {
|
||||
return s.repository.FindByName(name)
|
||||
}
|
||||
|
||||
func (s *field) Find() ([]*types.Field, error) {
|
||||
return s.repository.Find()
|
||||
}
|
||||
|
||||
+28
-20
@@ -8,41 +8,49 @@ import (
|
||||
|
||||
type (
|
||||
module struct {
|
||||
repository moduleRepository
|
||||
repository repository.Module
|
||||
}
|
||||
|
||||
moduleRepository interface {
|
||||
FindByID(ctx context.Context, moduleID uint64) (*types.Module, error)
|
||||
Find(ctx context.Context) ([]*types.Module, error)
|
||||
ModuleService interface {
|
||||
With(ctx context.Context) ModuleService
|
||||
|
||||
Create(ctx context.Context, module *types.Module) (*types.Module, error)
|
||||
Update(ctx context.Context, module *types.Module) (*types.Module, error)
|
||||
DeleteByID(ctx context.Context, moduleID uint64) error
|
||||
FindByID(moduleID uint64) (*types.Module, error)
|
||||
Find() ([]*types.Module, error)
|
||||
|
||||
Create(module *types.Module) (*types.Module, error)
|
||||
Update(module *types.Module) (*types.Module, error)
|
||||
DeleteByID(moduleID uint64) error
|
||||
}
|
||||
)
|
||||
|
||||
func Module() module {
|
||||
return module{
|
||||
repository: repository.Module(),
|
||||
func Module() ModuleService {
|
||||
return &module{
|
||||
repository: repository.NewModule(context.Background()),
|
||||
}
|
||||
}
|
||||
|
||||
func (svc module) FindByID(ctx context.Context, id uint64) (*types.Module, error) {
|
||||
return svc.repository.FindByID(ctx, id)
|
||||
func (s *module) With(ctx context.Context) ModuleService {
|
||||
return &module{
|
||||
repository: s.repository.With(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (svc module) Find(ctx context.Context) ([]*types.Module, error) {
|
||||
return svc.repository.Find(ctx)
|
||||
func (s *module) FindByID(id uint64) (*types.Module, error) {
|
||||
return s.repository.FindByID(id)
|
||||
}
|
||||
|
||||
func (svc module) Create(ctx context.Context, mod *types.Module) (*types.Module, error) {
|
||||
return svc.repository.Create(ctx, mod)
|
||||
func (s *module) Find() ([]*types.Module, error) {
|
||||
return s.repository.Find()
|
||||
}
|
||||
|
||||
func (svc module) Update(ctx context.Context, mod *types.Module) (*types.Module, error) {
|
||||
return svc.repository.Update(ctx, mod)
|
||||
func (s *module) Create(mod *types.Module) (*types.Module, error) {
|
||||
return s.repository.Create(mod)
|
||||
}
|
||||
|
||||
func (svc module) DeleteByID(ctx context.Context, id uint64) error {
|
||||
return svc.repository.DeleteByID(ctx, id)
|
||||
func (s *module) Update(mod *types.Module) (*types.Module, error) {
|
||||
return s.repository.Update(mod)
|
||||
}
|
||||
|
||||
func (s *module) DeleteByID(id uint64) error {
|
||||
return s.repository.DeleteByID(id)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user