Commit 57f2fa71 authored by Vojtech Sodoma's avatar Vojtech Sodoma

Merge branch '3386-add-user-labels' into 'master'

3386 add user labels

See merge request !63
parents 02ba5e47 a2f70a65
xivo-dao (2020.11.00) xivo-freya; urgency=medium
* 3386 - add labels and user labels
-- Laurent Meiller <[email protected]> Tue, 23 Jun 2020 15:04:11 +0000
xivo-dao (2020.10.00) xivo-freya; urgency=medium
* 3366 - update python lib for Debian10
......
db:
image: postgres:9.4
image: postgres:11.2
expose:
- "5432"
environment:
......
......@@ -20,6 +20,8 @@
from xivo_dao.alchemy.cti_profile import CtiProfile
from xivo_dao.alchemy.extension import Extension
from xivo_dao.alchemy.linefeatures import LineFeatures
from xivo_dao.alchemy.userlabels import UserLabels
from xivo_dao.alchemy.user_line import UserLine
from xivo_dao.alchemy.userfeatures import UserFeatures
from xivo_dao.alchemy.labels import Labels
from xivo_dao.alchemy.voicemail import Voicemail
......@@ -67,6 +67,7 @@ from xivo_dao.alchemy.groupfeatures import GroupFeatures
from xivo_dao.alchemy.iaxcallnumberlimits import IAXCallNumberLimits
from xivo_dao.alchemy.incall import Incall
from xivo_dao.alchemy.infos import Infos
from xivo_dao.alchemy.labels import Labels
from xivo_dao.alchemy.ldapfilter import LdapFilter
from xivo_dao.alchemy.ldapserver import LdapServer
from xivo_dao.alchemy.linefeatures import LineFeatures
......@@ -136,6 +137,7 @@ from xivo_dao.alchemy.user_line import UserLine
from xivo_dao.alchemy.usercustom import UserCustom
from xivo_dao.alchemy.userfeatures import UserFeatures
from xivo_dao.alchemy.useriax import UserIAX
from xivo_dao.alchemy.userlabels import UserLabels
from xivo_dao.alchemy.users import Users
from xivo_dao.alchemy.usersip import UserSIP
from xivo_dao.alchemy.voicemail import Voicemail
......
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
from sqlalchemy import select, func
from sqlalchemy.orm import relationship, column_property
from sqlalchemy.schema import Column, PrimaryKeyConstraint
from sqlalchemy.types import Integer, String, Text
from xivo_dao.alchemy import UserLabels
from xivo_dao.helpers.db_manager import Base
class Labels(Base):
__tablename__ = 'labels'
__table_args__ = (
PrimaryKeyConstraint('id'),
)
id = Column(Integer, nullable=False, autoincrement=True)
display_name = Column(String(128), nullable=False, unique=True)
description = Column(Text)
user_features = relationship("UserFeatures", secondary="userlabels", back_populates="labels")
users_count = column_property(
select([func.count(UserLabels.id)])
.where(UserLabels.label_id == id)
.correlate_except(UserLabels)
)
......@@ -17,16 +17,16 @@
from __future__ import unicode_literals
import uuid
import re
import uuid
from sqlalchemy.schema import Column, ForeignKey, PrimaryKeyConstraint, Index, \
UniqueConstraint, ForeignKeyConstraint
from sqlalchemy.types import Integer, String, Text, Boolean
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship, column_property
from sqlalchemy.orm.properties import ColumnProperty
from sqlalchemy.schema import Column, ForeignKey, PrimaryKeyConstraint, Index, \
UniqueConstraint, ForeignKeyConstraint
from sqlalchemy.sql import func, cast, not_
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.types import Integer, String, Text, Boolean
from xivo_dao.alchemy import enum
from xivo_dao.alchemy.cti_profile import CtiProfile
......@@ -59,7 +59,6 @@ caller_id_regex = re.compile(r'''
class UserFeatures(Base):
__tablename__ = 'userfeatures'
__table_args__ = (
PrimaryKeyConstraint('id'),
......@@ -143,6 +142,7 @@ class UserFeatures(Base):
UserLine.main_line == True)""")
voicemail = relationship("Voicemail")
cti_profile = relationship("CtiProfile")
labels = relationship("Labels", secondary="userlabels", back_populates="user_features")
def extrapolate_caller_id(self, extension=None):
default_num = extension.exten if extension else None
......
# -*- coding: utf-8 -*-
# Copyright (C) 2020 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.schema import Column
from sqlalchemy.types import Integer
from xivo_dao.helpers.db_manager import Base
class UserLabels(Base):
__tablename__ = 'userlabels'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('userfeatures.id', ondelete='CASCADE'))
label_id = Column(Integer, ForeignKey('labels.id', ondelete='CASCADE'))
user_features = relationship("UserFeatures", backref=backref("userlabels"))
labels = relationship("Labels", backref=backref("userlabels"))
# -*- coding: utf-8 -*-
# Copyright (C) 2014 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
# -*- coding: utf-8 -*-
# Copyright (C) 2020 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
from xivo_dao.alchemy.labels import Labels
from xivo_dao.helpers.db_manager import Session
from xivo_dao.helpers.db_manager import daosession
from xivo_dao.resources.labels.search import label_search
from xivo_dao.resources.utils.search import SearchResult
@daosession
def exists(session, label_id):
query = (session.query(Labels)
.filter(Labels.id == label_id)
)
return query.count() > 0
def get(label_id):
query = Session.query(Labels).filter_by(id=label_id)
return query.first()
def search(**parameters):
rows, total = label_search.search(Session, parameters)
return SearchResult(total, rows)
# -*- coding: UTF-8 -*-
# Copyright (C) 2020 Avencall
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from xivo_dao.alchemy.labels import Labels
from xivo_dao.resources.utils.search import SearchSystem
from xivo_dao.resources.utils.search import SearchConfig
config = SearchConfig(table=Labels,
columns={'id': Labels.id,
'display_name': Labels.display_name},
search=['display_name'],
default_sort='display_name')
label_search = SearchSystem(config)
# -*- coding: utf-8 -*-
# Copyright (C) 2014 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
from hamcrest import assert_that, equal_to
from xivo_dao.resources.utils.search import SearchResult
from xivo_dao.tests.test_dao import DAOTestCase
from xivo_dao.resources.labels import dao as label_dao
from xivo_dao.resources.user import dao as user_dao
class TestLabelExist(DAOTestCase):
def test_given_no_label_then_returns_false(self):
result = label_dao.exists(1)
assert_that(result, equal_to(False))
def test_given_label_exists_then_return_true(self):
label_row = self.add_label()
result = label_dao.exists(label_row.id)
assert_that(result, equal_to(True))
def test_get_all_labels(self):
self.add_user(callerid='"John Doe"')
label_row = self.add_label()
result = label_dao.search()
expected = SearchResult(total=1, items=[label_row])
assert_that(result[1][0].users_count, equal_to(0))
assert_that(result, equal_to(expected))
def test_get_all_labels_with_associated_user(self):
label_row = self.add_label()
user = self.add_user(callerid='"John Doe"')
user.labels.append(label_row)
result = label_dao.search()
expected = SearchResult(total=1, items=[label_row])
assert_that(result[1][0].users_count, equal_to(1))
assert_that(result, equal_to(expected))
......@@ -49,6 +49,7 @@ from xivo_dao.alchemy.func_key_type import FuncKeyType
from xivo_dao.alchemy.groupfeatures import GroupFeatures
from xivo_dao.alchemy.incall import Incall
from xivo_dao.alchemy.infos import Infos
from xivo_dao.alchemy.labels import Labels
from xivo_dao.alchemy.linefeatures import LineFeatures
from xivo_dao.alchemy.mediaserver import MediaServer
from xivo_dao.alchemy.meetmefeatures import MeetmeFeatures
......@@ -863,3 +864,11 @@ class DAOTestCase(unittest.TestCase):
def _random_name(self, length=6):
return ''.join(random.choice(string.lowercase) for _ in range(length))
def add_label(self, **kwargs):
kwargs.setdefault('id', self._generate_int())
kwargs.setdefault('display_name', self._random_name())
kwargs.setdefault('description', self._random_name(400))
label = Labels(**kwargs)
self.add_me(label)
return label
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment