Rename content to record on crm/types
This commit is contained in:
committed by
Denis Arh
parent
5584e6a2c9
commit
fffcf7fa08
@@ -17,16 +17,16 @@ type (
|
||||
ContentRepository interface {
|
||||
With(ctx context.Context, db *factory.DB) ContentRepository
|
||||
|
||||
FindByID(id uint64) (*types.Content, error)
|
||||
FindByID(id uint64) (*types.Record, error)
|
||||
|
||||
Report(moduleID uint64, params *types.ContentReport) (results interface{}, err error)
|
||||
Report(moduleID uint64, params *types.RecordReport) (results interface{}, err error)
|
||||
Find(moduleID uint64, query string, page int, perPage int, sort string) (*FindResponse, error)
|
||||
|
||||
Create(mod *types.Content) (*types.Content, error)
|
||||
Update(mod *types.Content) (*types.Content, error)
|
||||
Create(mod *types.Record) (*types.Record, error)
|
||||
Update(mod *types.Record) (*types.Record, error)
|
||||
DeleteByID(id uint64) error
|
||||
|
||||
Fields(mod *types.Content) ([]*types.ContentColumn, error)
|
||||
Fields(mod *types.Record) ([]*types.RecordColumn, error)
|
||||
}
|
||||
|
||||
FindResponseMeta struct {
|
||||
@@ -39,7 +39,7 @@ type (
|
||||
|
||||
FindResponse struct {
|
||||
Meta FindResponseMeta `json:"meta"`
|
||||
Contents []*types.Content `json:"contents"`
|
||||
Contents []*types.Record `json:"contents"`
|
||||
}
|
||||
|
||||
content struct {
|
||||
@@ -59,15 +59,15 @@ func (r *content) With(ctx context.Context, db *factory.DB) ContentRepository {
|
||||
|
||||
// @todo: update to accepted DeletedAt column semantics from SAM
|
||||
|
||||
func (r *content) FindByID(id uint64) (*types.Content, error) {
|
||||
mod := &types.Content{}
|
||||
func (r *content) FindByID(id uint64) (*types.Record, error) {
|
||||
mod := &types.Record{}
|
||||
if err := r.db().Get(mod, "SELECT * FROM crm_record WHERE id=? and deleted_at IS NULL", id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
func (r *content) Report(moduleID uint64, params *types.ContentReport) (results interface{}, err error) {
|
||||
func (r *content) Report(moduleID uint64, params *types.RecordReport) (results interface{}, err error) {
|
||||
crb := NewContentReportBuilder(moduleID, params)
|
||||
|
||||
var result = make([]map[string]interface{}, 0)
|
||||
@@ -105,7 +105,7 @@ func (r *content) Find(moduleID uint64, query string, page int, perPage int, sor
|
||||
Query: query,
|
||||
Sort: sort,
|
||||
},
|
||||
Contents: make([]*types.Content, 0),
|
||||
Contents: make([]*types.Record, 0),
|
||||
}
|
||||
|
||||
query = "%" + query + "%"
|
||||
@@ -215,27 +215,27 @@ func (r *content) Find(moduleID uint64, query string, page int, perPage int, sor
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (r *content) Create(mod *types.Content) (*types.Content, error) {
|
||||
func (r *content) Create(mod *types.Record) (*types.Record, error) {
|
||||
mod.ID = factory.Sonyflake.NextID()
|
||||
mod.CreatedAt = time.Now()
|
||||
mod.UserID = Identity(r.Context())
|
||||
|
||||
fields := make([]types.ContentColumn, 0)
|
||||
fields := make([]types.RecordColumn, 0)
|
||||
if err := json.Unmarshal(mod.Fields, &fields); err != nil {
|
||||
return nil, errors.Wrap(err, "No content")
|
||||
}
|
||||
|
||||
r.db().Exec("delete from crm_record_links where record_id=?", mod.ID)
|
||||
for _, v := range fields {
|
||||
v.ContentID = mod.ID
|
||||
v.RecordID = mod.ID
|
||||
if err := r.db().Replace("crm_record_column", v); err != nil {
|
||||
return nil, errors.Wrap(err, "Error adding columns")
|
||||
}
|
||||
for _, related := range v.Related {
|
||||
row := types.Related{
|
||||
ContentID: v.ContentID,
|
||||
Name: v.Name,
|
||||
RelatedContentID: related,
|
||||
RecordID: v.RecordID,
|
||||
Name: v.Name,
|
||||
RelatedRecordID: related,
|
||||
}
|
||||
if err := r.db().Replace("crm_record_links", row); err != nil {
|
||||
return nil, errors.Wrap(err, "Error adding column links")
|
||||
@@ -249,26 +249,26 @@ func (r *content) Create(mod *types.Content) (*types.Content, error) {
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
func (r *content) Update(mod *types.Content) (*types.Content, error) {
|
||||
func (r *content) Update(mod *types.Record) (*types.Record, error) {
|
||||
now := time.Now()
|
||||
mod.UpdatedAt = &now
|
||||
|
||||
fields := make([]types.ContentColumn, 0)
|
||||
fields := make([]types.RecordColumn, 0)
|
||||
if err := json.Unmarshal(mod.Fields, &fields); err != nil {
|
||||
return nil, errors.Wrap(err, "Error when saving content, no content")
|
||||
}
|
||||
|
||||
r.db().Exec("delete from crm_record_links where record_id=?", mod.ID)
|
||||
for _, v := range fields {
|
||||
v.ContentID = mod.ID
|
||||
v.RecordID = mod.ID
|
||||
if err := r.db().Replace("crm_record_column", v); err != nil {
|
||||
return nil, errors.Wrap(err, "Error adding columns to database")
|
||||
}
|
||||
for _, related := range v.Related {
|
||||
row := types.Related{
|
||||
ContentID: v.ContentID,
|
||||
Name: v.Name,
|
||||
RelatedContentID: related,
|
||||
RecordID: v.RecordID,
|
||||
Name: v.Name,
|
||||
RelatedRecordID: related,
|
||||
}
|
||||
if err := r.db().Replace("crm_record_links", row); err != nil {
|
||||
return nil, errors.Wrap(err, "Error adding column links")
|
||||
@@ -284,8 +284,8 @@ func (r *content) DeleteByID(id uint64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *content) Fields(content *types.Content) ([]*types.ContentColumn, error) {
|
||||
result := make([]*types.ContentColumn, 0)
|
||||
func (r *content) Fields(content *types.Record) ([]*types.RecordColumn, error) {
|
||||
result := make([]*types.RecordColumn, 0)
|
||||
module := Module(r.ctx, r.db())
|
||||
|
||||
mod, err := module.FindByID(content.ModuleID)
|
||||
|
||||
@@ -18,7 +18,7 @@ type (
|
||||
jsonField string
|
||||
|
||||
moduleID uint64
|
||||
params *types.ContentReport
|
||||
params *types.RecordReport
|
||||
}
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ var (
|
||||
contentReportExprMatch = regexp.MustCompile(`^\s*(\w+)\((.+)\)\s*$`)
|
||||
)
|
||||
|
||||
func NewContentReportBuilder(moduleID uint64, params *types.ContentReport) *contentReportBuilder {
|
||||
func NewContentReportBuilder(moduleID uint64, params *types.RecordReport) *contentReportBuilder {
|
||||
return &contentReportBuilder{
|
||||
moduleID: moduleID,
|
||||
params: params,
|
||||
|
||||
@@ -26,16 +26,16 @@ type (
|
||||
ContentService interface {
|
||||
With(ctx context.Context) ContentService
|
||||
|
||||
FindByID(contentID uint64) (*types.Content, error)
|
||||
FindByID(contentID uint64) (*types.Record, error)
|
||||
|
||||
Report(moduleID uint64, params *types.ContentReport) (interface{}, error)
|
||||
Report(moduleID uint64, params *types.RecordReport) (interface{}, error)
|
||||
Find(moduleID uint64, query string, page int, perPage int, sort string) (*repository.FindResponse, error)
|
||||
|
||||
Create(content *types.Content) (*types.Content, error)
|
||||
Update(content *types.Content) (*types.Content, error)
|
||||
Create(content *types.Record) (*types.Record, error)
|
||||
Update(content *types.Record) (*types.Record, error)
|
||||
DeleteByID(contentID uint64) error
|
||||
|
||||
Fields(mod *types.Content) ([]*types.ContentColumn, error)
|
||||
Fields(mod *types.Record) ([]*types.RecordColumn, error)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -56,7 +56,7 @@ func (s *content) With(ctx context.Context) ContentService {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *content) FindByID(id uint64) (*types.Content, error) {
|
||||
func (s *content) FindByID(id uint64) (*types.Record, error) {
|
||||
response, err := s.repository.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -64,7 +64,7 @@ func (s *content) FindByID(id uint64) (*types.Content, error) {
|
||||
return response, s.preload(response, "page", "user", "fields")
|
||||
}
|
||||
|
||||
func (s *content) Report(moduleID uint64, params *types.ContentReport) (interface{}, error) {
|
||||
func (s *content) Report(moduleID uint64, params *types.RecordReport) (interface{}, error) {
|
||||
return s.repository.Report(moduleID, params)
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func (s *content) Find(moduleID uint64, query string, page int, perPage int, sor
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *content) Create(mod *types.Content) (*types.Content, error) {
|
||||
func (s *content) Create(mod *types.Record) (*types.Record, error) {
|
||||
response, err := s.repository.Create(mod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -87,7 +87,7 @@ func (s *content) Create(mod *types.Content) (*types.Content, error) {
|
||||
return response, s.preload(response, "user", "fields")
|
||||
}
|
||||
|
||||
func (s *content) Update(content *types.Content) (c *types.Content, err error) {
|
||||
func (s *content) Update(content *types.Record) (c *types.Record, err error) {
|
||||
validate := func() error {
|
||||
if content.ID == 0 {
|
||||
return errors.New("Error updating content: invalid ID")
|
||||
@@ -110,7 +110,7 @@ func (s *content) Update(content *types.Content) (c *types.Content, err error) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *content) Fields(mod *types.Content) ([]*types.ContentColumn, error) {
|
||||
func (s *content) Fields(mod *types.Record) ([]*types.RecordColumn, error) {
|
||||
return s.repository.Fields(mod)
|
||||
}
|
||||
|
||||
|
||||
@@ -62,26 +62,26 @@ func TestContent(t *testing.T) {
|
||||
assert(t, module.ID > 0, "Expected auto generated ID")
|
||||
}
|
||||
|
||||
columns := []types.ContentColumn{
|
||||
types.ContentColumn{
|
||||
columns := []types.RecordColumn{
|
||||
types.RecordColumn{
|
||||
Name: "name",
|
||||
Value: "Tit Petric",
|
||||
},
|
||||
types.ContentColumn{
|
||||
types.RecordColumn{
|
||||
Name: "email",
|
||||
Value: "tit.petric@example.com",
|
||||
},
|
||||
types.ContentColumn{
|
||||
types.RecordColumn{
|
||||
Name: "options",
|
||||
Related: []string{"1", "2", "3"},
|
||||
},
|
||||
types.ContentColumn{
|
||||
types.RecordColumn{
|
||||
Name: "description",
|
||||
Value: "jack of all trades",
|
||||
},
|
||||
}
|
||||
|
||||
content1 := &types.Content{
|
||||
content1 := &types.Record{
|
||||
ModuleID: module.ID,
|
||||
}
|
||||
(&content1.Fields).Scan(func() []byte {
|
||||
@@ -89,26 +89,26 @@ func TestContent(t *testing.T) {
|
||||
return b
|
||||
}())
|
||||
|
||||
columns2 := []types.ContentColumn{
|
||||
types.ContentColumn{
|
||||
columns2 := []types.RecordColumn{
|
||||
types.RecordColumn{
|
||||
Name: "name",
|
||||
Value: "Marko Novak",
|
||||
},
|
||||
types.ContentColumn{
|
||||
types.RecordColumn{
|
||||
Name: "email",
|
||||
Value: "marko.n@example.com",
|
||||
},
|
||||
types.ContentColumn{
|
||||
types.RecordColumn{
|
||||
Name: "options",
|
||||
Related: []string{"1", "2", "3"},
|
||||
},
|
||||
types.ContentColumn{
|
||||
types.RecordColumn{
|
||||
Name: "description",
|
||||
Value: "persona non grata",
|
||||
},
|
||||
}
|
||||
|
||||
content2 := &types.Content{
|
||||
content2 := &types.Record{
|
||||
ModuleID: module.ID,
|
||||
}
|
||||
(&content2.Fields).Scan(func() []byte {
|
||||
@@ -156,7 +156,7 @@ func TestContent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
{
|
||||
fields := make([]types.ContentColumn, 0)
|
||||
fields := make([]types.RecordColumn, 0)
|
||||
err := json.Unmarshal(ms.Fields, &fields)
|
||||
assert(t, err == nil, "%+v", errors.Wrap(err, "Didn't expect error when unmarshalling"))
|
||||
assert(t, len(fields) == len(columns), "Expected different field count: %d != %d", 2, len(fields))
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/crusttech/crust/crm/types"
|
||||
)
|
||||
|
||||
func (r *content) preloadAll(contents []*types.Content, fields ...string) error {
|
||||
func (r *content) preloadAll(contents []*types.Record, fields ...string) error {
|
||||
for _, content := range contents {
|
||||
if err := r.preload(content, fields...); err != nil {
|
||||
return err
|
||||
@@ -15,7 +15,7 @@ func (r *content) preloadAll(contents []*types.Content, fields ...string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *content) preload(content *types.Content, fields ...string) (err error) {
|
||||
func (r *content) preload(content *types.Record, fields ...string) (err error) {
|
||||
for _, field := range fields {
|
||||
switch field {
|
||||
case "fields":
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
ContentReport struct {
|
||||
Metrics []ContentReportMetric
|
||||
Dimensions []ContentReportDimensions
|
||||
}
|
||||
|
||||
ContentReportMetric struct {
|
||||
Alias string
|
||||
Expression string
|
||||
}
|
||||
|
||||
ContentReportDimensions struct {
|
||||
Alias string
|
||||
Field string
|
||||
Modifiers []string
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
contentReportMetricScanRE *regexp.Regexp
|
||||
contentReportDimensionScanRE *regexp.Regexp
|
||||
)
|
||||
|
||||
func init() {
|
||||
contentReportMetricScanRE = regexp.MustCompile("^(?:(\\w+):)?(.+)$")
|
||||
contentReportDimensionScanRE = regexp.MustCompile("^(?:(\\w+):)?(\\w+)((?:\\|?\\w+)+)?$")
|
||||
}
|
||||
|
||||
func (r *ContentReport) ScanMetrics(metrics ...string) {
|
||||
r.Metrics = make([]ContentReportMetric, len(metrics))
|
||||
for i := 0; i < len(metrics); i++ {
|
||||
r.Metrics[i].Scan(metrics[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ContentReport) ScanDimensions(dimensions ...string) {
|
||||
r.Dimensions = make([]ContentReportDimensions, len(dimensions))
|
||||
for i := 0; i < len(dimensions); i++ {
|
||||
r.Dimensions[i].Scan(dimensions[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ContentReportMetric) Scan(metric string) {
|
||||
if match := contentReportMetricScanRE.FindStringSubmatch(metric); len(match) == 3 {
|
||||
m.Alias = match[1]
|
||||
m.Expression = match[2]
|
||||
}
|
||||
}
|
||||
|
||||
func (d *ContentReportDimensions) Scan(dimension string) {
|
||||
if match := contentReportDimensionScanRE.FindStringSubmatch(dimension); len(match) == 4 {
|
||||
d.Alias = match[1]
|
||||
d.Field = match[2]
|
||||
|
||||
if len(match[3]) > 0 {
|
||||
d.Modifiers = strings.Split(match[3][1:], "|")
|
||||
}
|
||||
}
|
||||
}
|
||||
66
crm/types/record_util.go
Normal file
66
crm/types/record_util.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
RecordReport struct {
|
||||
Metrics []RecordReportMetric
|
||||
Dimensions []RecordReportDimensions
|
||||
}
|
||||
|
||||
RecordReportMetric struct {
|
||||
Alias string
|
||||
Expression string
|
||||
}
|
||||
|
||||
RecordReportDimensions struct {
|
||||
Alias string
|
||||
Field string
|
||||
Modifiers []string
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
recordReportMetricScanRE *regexp.Regexp
|
||||
recordReportDimensionScanRE *regexp.Regexp
|
||||
)
|
||||
|
||||
func init() {
|
||||
recordReportMetricScanRE = regexp.MustCompile("^(?:(\\w+):)?(.+)$")
|
||||
recordReportDimensionScanRE = regexp.MustCompile("^(?:(\\w+):)?(\\w+)((?:\\|?\\w+)+)?$")
|
||||
}
|
||||
|
||||
func (r *RecordReport) ScanMetrics(metrics ...string) {
|
||||
r.Metrics = make([]RecordReportMetric, len(metrics))
|
||||
for i := 0; i < len(metrics); i++ {
|
||||
r.Metrics[i].Scan(metrics[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RecordReport) ScanDimensions(dimensions ...string) {
|
||||
r.Dimensions = make([]RecordReportDimensions, len(dimensions))
|
||||
for i := 0; i < len(dimensions); i++ {
|
||||
r.Dimensions[i].Scan(dimensions[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (m *RecordReportMetric) Scan(metric string) {
|
||||
if match := recordReportMetricScanRE.FindStringSubmatch(metric); len(match) == 3 {
|
||||
m.Alias = match[1]
|
||||
m.Expression = match[2]
|
||||
}
|
||||
}
|
||||
|
||||
func (d *RecordReportDimensions) Scan(dimension string) {
|
||||
if match := recordReportDimensionScanRE.FindStringSubmatch(dimension); len(match) == 4 {
|
||||
d.Alias = match[1]
|
||||
d.Field = match[2]
|
||||
|
||||
if len(match[3]) > 0 {
|
||||
d.Modifiers = strings.Split(match[3][1:], "|")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestContentReport(t *testing.T) {
|
||||
r := &ContentReport{}
|
||||
func TestRecordReport(t *testing.T) {
|
||||
r := &RecordReport{}
|
||||
r.ScanMetrics("alias:exp")
|
||||
if len(r.Metrics) == 0 {
|
||||
t.Log("No metrics scanned")
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// Content is a stored row in the `record` table
|
||||
Content struct {
|
||||
// Record is a stored row in the `record` table
|
||||
Record struct {
|
||||
ID uint64 `json:"contentID,string" db:"id"`
|
||||
ModuleID uint64 `json:"moduleID,string" db:"module_id"`
|
||||
|
||||
@@ -29,20 +29,20 @@ type (
|
||||
DeletedAt *time.Time `db:"deleted_at" json:"deletedAt,omitempty"`
|
||||
}
|
||||
|
||||
// ContentColumn is a stored row in the `record_column` table
|
||||
ContentColumn struct {
|
||||
ContentID uint64 `json:"-" db:"record_id"`
|
||||
Name string `json:"name" db:"column_name"`
|
||||
Value string `json:"value" db:"column_value"`
|
||||
Related []string `json:"related" db:"-"`
|
||||
// RecordColumn is a stored row in the `record_column` table
|
||||
RecordColumn struct {
|
||||
RecordID uint64 `json:"-" db:"record_id"`
|
||||
Name string `json:"name" db:"column_name"`
|
||||
Value string `json:"value" db:"column_value"`
|
||||
Related []string `json:"related" db:"-"`
|
||||
}
|
||||
|
||||
Related struct {
|
||||
ContentID uint64 `json:"-" db:"record_id"`
|
||||
Name string `json:"-" db:"column_name"`
|
||||
RecordID uint64 `json:"-" db:"record_id"`
|
||||
Name string `json:"-" db:"column_name"`
|
||||
|
||||
// RelatedContentID isn't necessarily a content ID (multiple-select anything goes options)
|
||||
RelatedContentID string `json:"-" db:"rel_record_id"`
|
||||
// RelatedRecordID isn't necessarily a record ID (multiple-select anything goes options)
|
||||
RelatedRecordID string `json:"-" db:"rel_record_id"`
|
||||
}
|
||||
|
||||
// Field - CRM input field definitions
|
||||
|
||||
Reference in New Issue
Block a user