/
filter.go
executable file
·147 lines (135 loc) · 5.85 KB
/
filter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2016 NDP Systèmes. All Rights Reserved.
// See LICENSE file for full licensing details.
package web
import (
"fmt"
"strings"
"github.com/gleke/web/odooproxy"
"github.com/gleke/hexya/src/models"
"github.com/gleke/hexya/src/models/fields"
"github.com/gleke/hexya/src/tools/strutils"
"github.com/gleke/pool/h"
"github.com/gleke/pool/m"
"github.com/gleke/pool/q"
)
var fields_Filter = map[string]models.FieldDefinition{
"Name": fields.Char{String: "Filter Name", Required: true},
"User": fields.Many2One{RelationModel: h.User(), OnDelete: models.Cascade,
Default: func(env models.Environment) interface{} {
return h.User().Search(env, q.User().ID().Equals(env.Uid()))
}, Help: `The user this filter is private to. When left empty the filter is public and available to all users.`},
"Domain": fields.Text{Required: true, Default: models.DefaultValue("[]")},
"Context": fields.Text{Required: true, Default: models.DefaultValue("{}")},
"Sort": fields.Text{Required: true, Default: models.DefaultValue("[]")},
"ResModel": fields.Char{String: "Model", Required: true, JSON: "model_id"},
"IsDefault": fields.Boolean{String: "Default filter"},
"Action": fields.Integer{
Help: `The menu action this filter applies to. When left empty the filter applies to all menus for this model.`,
JSON: "action_id"},
"Active": fields.Boolean{Default: models.DefaultValue(true), Required: true},
}
// GetFilters returns the filters for the given model and actionID for the current user
func filter_GetFilters(rs m.FilterSet, modelName string, actionID int64) []m.FilterData {
modelName = odooproxy.ConvertModelName(modelName)
actionCondition := rs.GetActionCondition(actionID)
filters := h.Filter().Search(rs.Env(), q.Filter().ResModel().Equals(modelName).
AndCond(actionCondition).
AndCond(q.Filter().UserFilteredOn(q.User().ID().Equals(rs.Env().Uid())).
Or().User().IsNull()))
userContext := h.User().BrowseOne(rs.Env(), rs.Env().Uid()).ContextGet()
res := filters.WithNewContext(userContext).All()
return res
}
func filter_Copy(rs m.FilterSet, overrides m.FilterData) m.FilterSet {
rs.EnsureOne()
overrides.SetName(fmt.Sprintf("%s (copy)", rs.Name()))
return rs.Super().Copy(overrides)
}
// CreateOrReplace creates or updates the filter with the given parameters.
// Filter is considered the same if it has the same name (case insensitive) and the same user (if it has one).
func filter_CreateOrReplace(rs m.FilterSet, vals m.FilterData) m.FilterSet {
if vals.HasDomain() {
dom := strutils.MarshalToJSONString(vals.Domain())
dom = strings.Replace(dom, "false", "False", -1)
dom = strings.Replace(dom, "true", "True", -1)
vals.SetDomain(dom)
}
vals.SetResModel(odooproxy.ConvertModelName(vals.ResModel()))
values := vals
currentFilters := rs.GetFilters(values.ResModel(), values.Action())
var matchingFilters []m.FilterData
for _, filter := range currentFilters {
if strings.ToLower(filter.Name()) != strings.ToLower(values.Name()) {
continue
}
if !filter.User().Equals(values.User()) {
continue
}
matchingFilters = append(matchingFilters, filter)
}
if values.IsDefault() {
if values.User().IsNotEmpty() {
// Setting new default: any other default that belongs to the user
// should be turned off
actionCondition := rs.GetActionCondition(values.Action())
defaults := h.Filter().Search(rs.Env(), actionCondition.
And().ResModel().Equals(values.ResModel()).
And().User().Equals(values.User()).
And().IsDefault().Equals(true))
if defaults.IsNotEmpty() {
defaults.SetIsDefault(false)
}
} else {
rs.CheckGlobalDefault(values, matchingFilters)
}
}
if len(matchingFilters) > 0 {
// When a filter exists for the same (name, model, user) triple, we simply
// replace its definition (considering action_id irrelevant here)
matchingFilter := h.Filter().BrowseOne(rs.Env(), matchingFilters[0].ID())
matchingFilter.Write(values)
return matchingFilter
}
return rs.Create(values)
}
// CheckGlobalDefault checks if there is a global default for the ResModel requested.
//
// If there is, and the default is different than the record being written
// (-> we're not updating the current global default), raise an error
// to avoid users unknowingly overwriting existing global defaults (they
// have to explicitly remove the current default before setting a new one)
//
// This method should only be called if 'vals' is trying to set 'IsDefault'
func filter_CheckGlobalDefault(rs m.FilterSet, values m.FilterData, matchingFilters []m.FilterData) {
actionCondition := rs.GetActionCondition(values.Action())
defaults := h.Filter().Search(rs.Env(), actionCondition.
And().ResModel().Equals(values.ResModel()).
And().User().IsNull().
And().IsDefault().Equals(true))
if defaults.IsEmpty() {
return
}
if len(matchingFilters) > 0 && matchingFilters[0].ID() == defaults.ID() {
return
}
log.Panic("There is already a shared filter set as default for this model, delete or change it before setting a new default", "model", values.ResModel)
}
// GetActionCondition returns a condition for matching filters that are visible in the
// same context (menu/view) as the given action.
func filter_GetActionCondition(_ m.FilterSet, action int64) q.FilterCondition {
if action != 0 {
// filters specific to this menu + global ones
return q.Filter().Action().Equals(action).Or().Action().IsNull()
}
return q.Filter().Action().IsNull()
}
func init() {
models.NewModel("Filter")
h.Filter().AddFields(fields_Filter)
h.Filter().AddSQLConstraint("name_model_uid_unique", "unique (name, model_id, user_id, action_id)", "Filter names must be unique")
h.Filter().NewMethod("GetFilters", filter_GetFilters)
h.Filter().Methods().Copy().Extend(filter_Copy)
h.Filter().NewMethod("CreateOrReplace", filter_CreateOrReplace)
h.Filter().NewMethod("CheckGlobalDefault", filter_CheckGlobalDefault)
h.Filter().NewMethod("GetActionCondition", filter_GetActionCondition)
}