File: //proc/thread-self/root/home/arjun/projects/buyercall/buyercall/blueprints/partnership/models.py
import uuid
import math
import logging
import traceback
from flask import jsonify
from datetime import datetime, timedelta, date as datetime_date
import pytz
from buyercall.blueprints.sms.models import Message
from buyercall.blueprints.user.models import User
from buyercall.blueprints.contacts.models import Contact, CreditReports
from buyercall.blueprints.widgets.models import Widget
from buyercall.blueprints.agents.models import Agent
from buyercall.blueprints.issue.models import Issue
<<<<<<< HEAD
from buyercall.blueprints.appointments.models import Appointment
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
from buyercall.blueprints.activity.models import ActivityLogs
from buyercall.lib.util_sqlalchemy import ResourceMixin
from buyercall.lib.util_datetime import convert_to_deltatime
from sqlalchemy.sql.expression import update
from buyercall.blueprints.billing.models.invoice import Invoice
from buyercall.blueprints.leads.models import Lead
from buyercall.extensions import db
from sqlalchemy import or_, and_, extract
from collections import OrderedDict
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.sql import text
<<<<<<< HEAD
from dateutil.relativedelta import relativedelta
from sqlalchemy.dialects.postgresql import UUID, ARRAY
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
from buyercall.blueprints.filters import format_phone_number
log = logging.getLogger(__name__)
BILLING_TYPE = OrderedDict([
('partnership', 'Bill Partnership'),
('account', 'Bill Account'),
('invoice', 'By Invoice')
])
BUSINESS_TYPE = OrderedDict([
('automotive', 'Automotive'),
('general', 'General'),
('healthcare', 'Healthcare')
])
CREDIT_PROVIDER = OrderedDict([
('', ''),
('offerlogix', 'OfferLogix')
])
class ApiToken(ResourceMixin, db.Model):
__tablename__ = 'api_tokens'
id = db.Column(db.Integer, primary_key=True)
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='0')
api_token_hash = db.Column(db.String(64), nullable=False)
@classmethod
def create(cls):
"""
Create a new api token
:return: int / id
"""
from buyercall.lib.util_crypto import SHA
token = str(uuid.uuid4())
new_api_token = ApiToken(
active=False,
api_token_hash=SHA.encrypt(token)
)
db.session.add(new_api_token)
db.session.flush()
result_api_id = new_api_token.id
db.session.commit()
return result_api_id
@classmethod
def check_token(cls, token):
"""
Check to see if REST API token is valid, return the id of the token
"""
found_token_id = -1
from buyercall.lib.util_crypto import SHA
token_hash = SHA.encrypt(token)
found_token_id = db.session.query(ApiToken.id) \
.filter(and_(ApiToken.active == True, ApiToken.api_token_hash == token_hash)) \
.first()
if found_token_id:
if len(found_token_id) >= 1:
found_token_id = found_token_id[0]
if found_token_id >= 1:
return found_token_id
return None
@classmethod
def regenerate_token(cls, id):
"""
Regenerate the token for a specific token entry. The new token is returned.
"""
token_hash = db.session.query(ApiToken) \
.filter(ApiToken.id == id) \
.first()
if token_hash is not None:
new_token = str(uuid.uuid4())
from buyercall.lib.util_crypto import SHA
api_token_hash = SHA.encrypt(new_token)
token_hash.api_token_hash = api_token_hash
token_hash.save()
db.session.commit()
return new_token
else:
return None
class ExternalApiServiceProviders(ResourceMixin, db.Model):
__tablename__ = 'external_api_service_providers'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), index=True, nullable=False,
server_default='')
@classmethod
def get_provider_name(cls, pa_external_api_service_provider_id):
"""
Returns the API service provider name. If one does not exist, an empty string is returned.
:return: external api service provider name
"""
result = ''
service_provider = db.session.query(ExternalApiServiceProviders) \
.filter(ExternalApiServiceProviders.id == pa_external_api_service_provider_id) \
.first()
if service_provider is not None:
result = service_provider.name
return result
class ExternalApiServiceProvidersPartnershipAccountTie(ResourceMixin, db.Model):
__tablename__ = 'external_api_service_providers_partnership_account_tie'
external_api_service_provider_id = db.Column(
db.Integer,
db.ForeignKey(
'external_api_service_providers.id',
name='partnership_account_external_api_tie_sp_id_fkey'
),
primary_key=True,
index=True
)
partnership_account_id = db.Column(
db.Integer,
db.ForeignKey(
'partnership_accounts.id',
name='partnership_account_external_api_tie_pa_fkey'
),
primary_key=True
)
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1')
username = db.Column(db.String(128), nullable=False, server_default='')
password = db.Column(db.String(128), nullable=False, server_default='')
url = db.Column(db.String(128), nullable=False, server_default='')
token_url = db.Column(db.String(128), nullable=False, server_default='')
client_id = db.Column(db.String(128), nullable=False, server_default='')
secret = db.Column(db.String(128), nullable=False, server_default='')
source = db.Column(db.String(128), nullable=False, server_default='')
app_source = db.Column(db.String(128), nullable=False, server_default='')
@classmethod
def delete(cls, pa_external_api_service_provider_id, pa_partnership_account_id):
"""
Delete the partnership account's external api service provider details.
:return: bool
"""
result = False
partnership_provider_tie = db.session.query(ExternalApiServiceProvidersPartnershipAccountTie).filter(
and_(ExternalApiServiceProvidersPartnershipAccountTie.partnership_account_id == pa_partnership_account_id,
ExternalApiServiceProvidersPartnershipAccountTie.external_api_service_provider_id ==
pa_external_api_service_provider_id)) \
.first()
if partnership_provider_tie is not None:
db.session.delete(partnership_provider_tie)
db.session.commit()
result = True
return result
@classmethod
def update(cls, pa_external_api_service_provider_id, pa_partnership_account_id, pa_client_id,
pa_username, pa_password, pa_url, pa_token_url, pa_source, pa_app_source, pa_secret):
"""
Update the partnership account's external api service provider details.
:return: bool
"""
partnership_provider_tie = db.session.query(ExternalApiServiceProvidersPartnershipAccountTie) \
.filter(
ExternalApiServiceProvidersPartnershipAccountTie.partnership_account_id == pa_partnership_account_id,
ExternalApiServiceProvidersPartnershipAccountTie.external_api_service_provider_id == pa_external_api_service_provider_id
).first()
if partnership_provider_tie is not None:
partnership_provider_tie.external_api_service_provider_id = pa_external_api_service_provider_id
partnership_provider_tie.username = pa_username
partnership_provider_tie.password = pa_password
partnership_provider_tie.url = pa_url
partnership_provider_tie.secret = pa_secret
partnership_provider_tie.client_id = pa_client_id
partnership_provider_tie.token_url = pa_token_url
partnership_provider_tie.source = pa_source
partnership_provider_tie.app_source = pa_app_source
db.session.commit()
return True
elif partnership_provider_tie is None:
partnership_provider_tie = ExternalApiServiceProvidersPartnershipAccountTie(
external_api_service_provider_id=pa_external_api_service_provider_id,
partnership_account_id=pa_partnership_account_id,
client_id=pa_client_id,
token_url=pa_token_url,
username=pa_username,
password=pa_password,
url=pa_url,
app_source=pa_app_source,
source=pa_source,
secret=pa_secret)
db.session.add(partnership_provider_tie)
db.session.flush()
db.session.commit()
return True
else:
return False
@classmethod
def exists(cls, pa_partnership_account_id, pa_service_provider_id):
"""
Check whether the partnership accounts is assigned to provided external api service provider.
:return: external api service provider id
"""
partnership_provider_tie = db.session.query(ExternalApiServiceProvidersPartnershipAccountTie) \
.filter(
ExternalApiServiceProvidersPartnershipAccountTie.partnership_account_id == pa_partnership_account_id,
ExternalApiServiceProvidersPartnershipAccountTie.external_api_service_provider_id == pa_service_provider_id
).first()
if partnership_provider_tie is not None:
return partnership_provider_tie.external_api_service_provider_id
return -1
@classmethod
def service_provider_name(cls, pa_partnership_account_id):
"""
Returns the API service provider name. If one does not exist, an empty string is returned.
:return: external api service provider name
"""
result = ''
partnership_provider_tie = db.session.query(ExternalApiServiceProvidersPartnershipAccountTie) \
.filter(
ExternalApiServiceProvidersPartnershipAccountTie.partnership_account_id == pa_partnership_account_id
).first()
if partnership_provider_tie is not None:
result = ExternalApiServiceProviders.get_provider_name(
partnership_provider_tie.external_api_service_provider_id
)
return result
@classmethod
def exists_for_service_provider(cls, partnership_account_id, service_provider_name):
"""
Check whether the partnership accounts is assigned to provided external api service provider.
:return: external api service provider object
"""
partnership_provider_tie = db.session \
.query(ExternalApiServiceProvidersPartnershipAccountTie) \
.join(ExternalApiServiceProviders) \
.filter(ExternalApiServiceProvidersPartnershipAccountTie.partnership_account_id == partnership_account_id,
ExternalApiServiceProvidersPartnershipAccountTie.active) \
.filter(ExternalApiServiceProviders.name == service_provider_name) \
.first()
return partnership_provider_tie
class PartnershipAccountGroupTie(ResourceMixin, db.Model):
__tablename__ = 'partnership_account_group_tie'
partnership_account_group_id = db.Column(
db.Integer,
db.ForeignKey(
'partnership_account_groups.id',
name='partnership_account_group_account_tie_id_fkey'
),
primary_key=False, index=True
)
partnership_account_id = db.Column(
db.Integer,
db.ForeignKey(
'partnership_accounts.id',
name='partnership_account_group_id_tie_fkey'
),
primary_key=True
)
@classmethod
def update(cls, pa_partnership_account_group_id, pa_partnership_account_id):
"""
Update the partnership account's group details.
:return: bool
"""
# account_group = db.session.query(PartnershipAccountGroupTie)\
# .filter(PartnershipAccountGroupTie.partnership_account_id == pa_partnership_account_id).first()
#
# if account_group is not None:
# account_group.partnership_account_group_id = pa_partnership_account_group_id
# db.session.commit()
# return True
# elif account_group is None:
# account_group = PartnershipAccountGroupTie(partnership_account_group_id = pa_partnership_account_group_id,
# partnership_account_id = pa_partnership_account_id)
# db.session.add(account_group)
# db.session.flush()
# db.session.commit()
# return True
# else:
return False
@classmethod
def exists(cls, partnership_account_group_id, partnership_account_id):
"""
Check whether the two partnership accounts are in the same group.
:return: bool
"""
account_group = db.session.query(PartnershipAccountGroupTie) \
.filter(and_(PartnershipAccountGroupTie.partnership_account_group_id == partnership_account_group_id,
PartnershipAccountGroupTie.partnership_account_id == partnership_account_id)).first()
if account_group is not None:
return True
else:
return False
<<<<<<< HEAD
class PartnershipAccountCreditTie(ResourceMixin, db.Model):
__tablename__ = 'partnership_account_credit_tie'
id = db.Column(db.Integer, primary_key=True)
service_provider = db.Column(db.String(128), index=True, nullable=False, server_default='')
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1')
partnership_account_id = db.Column(db.Integer, db.ForeignKey('partnership_accounts.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=False)
product_type = db.Column(db.String(128), index=True, nullable=False, server_default='')
api_account = db.Column(db.String(256), index=True, nullable=False, server_default='')
api_username = db.Column(db.String(256), index=True, nullable=False, server_default='')
api_password = db.Column(db.String(256), index=True, nullable=False, server_default='')
experian_enabled = db.Column('experian_enabled', db.Boolean(), nullable=False, server_default='0')
transunion_enabled = db.Column('transunion_enabled', db.Boolean(), nullable=False, server_default='0')
equifax_enabled = db.Column('equifax_enabled', db.Boolean(), nullable=False, server_default='0')
@classmethod
def partner_account_seven_hundred_credit_info(cls, paid, product_type):
"""
Find and return the partnership account's 700 credit credentials.
"""
seven_hundred_credit_as_provider = (db.session.query(cls)) \
.filter(cls.partnership_account_id == paid,
cls.service_provider == '700Credit',
cls.product_type == product_type,
cls.active.is_(True)).first()
if seven_hundred_credit_as_provider is not None:
return seven_hundred_credit_as_provider
else:
return None
@classmethod
def partner_account_finserv_credit_info(cls, paid, product_type):
"""
Find and return the partnership account's Finserv credit credentials.
"""
finserv_credit_as_provider = (db.session.query(cls)) \
.filter(cls.partnership_account_id == paid,
cls.service_provider == 'Finserv',
cls.product_type == product_type,
cls.active.is_(True)).first()
if finserv_credit_as_provider is not None:
return finserv_credit_as_provider
else:
return None
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
class PartnershipAccountGroup(ResourceMixin, db.Model):
__tablename__ = 'partnership_account_groups'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), index=True, nullable=False,
server_default='')
<<<<<<< HEAD
=======
class PartnershipAccountCreditTie(ResourceMixin, db.Model):
__tablename__ = 'partnership_account_credit_tie'
id = db.Column(db.Integer, primary_key=True)
service_provider = db.Column(db.String(128), index=True, nullable=False, server_default='')
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1')
partnership_account_id = db.Column(db.Integer, db.ForeignKey('partnership_accounts.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=False)
product_type = db.Column(db.String(128), index=True, nullable=False, server_default='')
api_account = db.Column(db.String(256), index=True, nullable=False, server_default='')
api_username = db.Column(db.String(256), index=True, nullable=False, server_default='')
api_password = db.Column(db.String(256), index=True, nullable=False, server_default='')
experian_enabled = db.Column('experian_enabled', db.Boolean(), nullable=False, server_default='0')
transunion_enabled = db.Column('transunion_enabled', db.Boolean(), nullable=False, server_default='0')
equifax_enabled = db.Column('equifax_enabled', db.Boolean(), nullable=False, server_default='0')
def __init__(self, *args, **kwargs):
super(PartnershipAccountCreditTie, self).__init__(*args, **kwargs)
@hybrid_property
def is_active(self):
return self.active
@is_active.expression
def is_active(cls):
return cls.active
@classmethod
def partner_account_seven_hundred_credit_info(cls, paid, product_type):
"""
Find and return a partnership account's 700 credit credentials.
"""
seven_hundred_credit_as_provider = (db.session.query(cls)) \
.filter(cls.partnership_account_id == paid,
cls.service_provider == '700Credit',
cls.product_type == product_type,
cls.active.is_(True)).first()
if seven_hundred_credit_as_provider is not None:
return seven_hundred_credit_as_provider
else:
return None
@classmethod
def partner_account_finserv_credit_info(cls, paid, product_type):
"""
Find and return a partnership account's Finserv credit credentials.
"""
finserv_credit_as_provider = (db.session.query(cls)) \
.filter(cls.partnership_account_id == paid,
cls.service_provider == 'Finserv',
cls.product_type == product_type,
cls.active.is_(True)).first()
if finserv_credit_as_provider is not None:
return finserv_credit_as_provider
else:
return None
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
class PartnershipAccount(ResourceMixin, db.Model):
__tablename__ = 'partnership_accounts'
# Serializing fields
serialize_only = ('sid', 'name', 'active', 'billing_type', 'business_type', 'appointment_enabled', 'email',
'description', 'safety_information', 'timezone')
id = db.Column(db.Integer, primary_key=True)
sid = db.Column(UUID(as_uuid=True), unique=True, default=uuid.uuid4, index=True)
name = db.Column(db.String(255), index=True, nullable=False,
server_default='')
partnership_id = db.Column(db.Integer, db.ForeignKey('partnerships.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=True)
subscription_id = db.Column(
db.Integer,
db.ForeignKey(
'subscriptions.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=True
)
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='0')
email = db.Column(db.String(320), index=True, nullable=False, server_default='')
adf_assigned_email = db.Column(db.String(255), nullable=True)
users = db.relationship(User, backref="partnership_account")
agents = db.relationship(Agent, backref="partnership_account")
issues = db.relationship(Issue, backref="partnership_account")
import_leads = db.Column('import_leads', db.Boolean(), nullable=False, server_default='0')
invoices = db.relationship(Invoice, backref='partnership_account')
leads = db.relationship(Lead, backref='partnership_account', passive_deletes=True)
appointments = db.relationship(Appointment, backref="partnership_account_appointments",
lazy='dynamic', passive_deletes=True)
messages = db.relationship(Message, backref="partnership_account", passive_deletes=True)
contacts = db.relationship(Contact, backref="partnership_account", uselist=False)
widgets = db.relationship(Widget, backref="partnership_account")
activity_logs = db.relationship(ActivityLogs, backref="partnership_account")
credit_provider = db.relationship(PartnershipAccountCreditTie, backref="partnership_account")
credit_reports = db.relationship(CreditReports, backref="partnership_account", uselist=False)
billing_type = db.Column(
db.Enum(*BILLING_TYPE, name='billing_types'),
index=True,
nullable=False,
server_default='partnership'
)
api_token_id = db.Column(
db.Integer,
db.ForeignKey(
'api_tokens.id',
onupdate='CASCADE',
ondelete='CASCADE'
),
index=True,
nullable=True
)
partner_account_code = db.Column(
db.String(64),
index=True,
nullable=False,
server_default=''
)
business_type = db.Column(
db.String(128), nullable=False, server_default='general',
index=True
)
is_2fa_email_enabled = db.Column(db.Boolean(), nullable=False,
server_default='0')
is_2fa_sms_enabled = db.Column(db.Boolean(), nullable=False,
server_default='1')
partnership_account_group = db.relationship(PartnershipAccountGroupTie, backref='partnership_account')
description = db.Column(db.String(1024), nullable=False, server_default='')
safety_information = db.Column(db.String(1024), nullable=False, server_default='')
address_1 = db.Column(db.String(128), nullable=False, server_default='')
address_2 = db.Column(db.String(128), nullable=False, server_default='')
city = db.Column(db.String(64), nullable=False, server_default='')
state = db.Column(db.String(64), nullable=False, server_default='')
zip_code = db.Column(db.String(10), nullable=False, server_default='')
country = db.Column(db.String(64), nullable=False, server_default='united states')
timezone = db.Column(db.String(64), nullable=False, server_default='US/Eastern')
operating_hours = db.relationship('PartnershipAccountOperatingHours', backref='partnership_account',
cascade='all, delete-orphan', lazy='dynamic',
order_by='asc(PartnershipAccountOperatingHours.day)')
# Indicates if appointments are enabled for the account
appointment_enabled = db.Column(db.Boolean, nullable=False, server_default='1')
# The time interval in minutes for how long appointments are
appointment_interval = db.Column(db.Integer, nullable=False, default=30)
# The general appointment slot count to determine how many a specific day slot can be booked
appointment_general_slot_count = db.Column(db.Integer, nullable=False, default=1)
# The service appointment slot count to determine how many a specific day slot can be booked
appointment_service_slot_count = db.Column(db.Integer, nullable=False, default=1)
# Whether the appointments all hours
all_hours = db.Column(db.Boolean, nullable=False, server_default='0')
# account invitation token
account_invitation_url_token = db.Column(
db.String(255),
index=True,
nullable=False,
server_default=''
)
# partnership_account_group_id = db.Column(db.Integerdb.ForeignKey('partnership_account_group_tie.partnerid',
# onupdate='CASCADE'),
# index=True, nullable=True, server_default=None)
# REST API authentication token
# api_token_hash = db.Column(db.String(60), nullable=True)
<<<<<<< HEAD
# @classmethod
# def create(cls, name, partnership_id, active, billing_type, email):
# """
# Create a partnership account.
#
# :return: bool
# """
# try:
# new_account = PartnershipAccount(
# name=name,
# partnership_id=partnership_id,
# active=active,
# billing_type=billing_type,
# email=email
# )
#
# api_token_id = ApiToken.create()
#
# if api_token_id is not None and api_token_id > 0:
# new_account.api_token_id = api_token_id
#
# db.session.add(new_account)
# db.session.commit()
# except Exception as e:
# print(e)
# return True
@classmethod
def get_by_email(cls, email):
return cls.query.filter(cls.email == email).first()
@classmethod
def get_name(cls, pid):
obj = cls.query.filter(cls.id == pid).first()
return obj.name if obj else None
@classmethod
def get_by_invitation_token(cls, token=None):
return cls.query.filter(cls.account_invitation_url_token == token).first() if token else None
@classmethod
def create_partial(cls, name, partnership_id, active, partner_account_code, description,
safety_information, address_1, address_2, city, state, zip_code, country, timezone,
business_type):
=======
@hybrid_property
def credit_sp(self):
for i in self.credit_provider:
return i.service_provider
@classmethod
def create(cls, name, partnership_id, active, billing_type):
"""
Create a partnership account.
:return: bool
"""
new_account = PartnershipAccount(
name=name,
partnership_id=partnership_id,
active=active,
billing_type=billing_type
)
api_token_id = ApiToken.create()
if api_token_id is not None and api_token_id > 0:
new_account.api_token_id = api_token_id
db.session.add(new_account)
db.session.commit()
return True
@classmethod
def create_partial(cls, name, partnership_id, active, partner_account_code, business_type=None):
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
"""
Create a partnership account.
:return: bool
"""
try:
subscription_id = Partnership.query \
.with_entities(Partnership.subscription_id) \
.filter(Partnership.id == partnership_id).first()
if business_type:
bt = business_type
else:
bt = 'general'
new_account = PartnershipAccount(
name=name,
partnership_id=partnership_id,
partner_account_code=partner_account_code,
subscription_id=subscription_id,
active=active,
<<<<<<< HEAD
billing_type='partnership',
description=description,
safety_information=safety_information,
address_1=address_1,
address_2=address_2,
city=city,
state=state,
zip_code=zip_code,
country=country,
timezone=timezone,
business_type=bt
=======
business_type=bt,
billing_type='partnership',
import_leads=False
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
)
api_token_id = ApiToken.create()
if api_token_id is not None and api_token_id > 0:
new_account.api_token_id = api_token_id
db.session.add(new_account)
db.session.flush()
partnership_account_id = new_account.id
db.session.commit()
return partnership_account_id
except Exception as e:
log.error('Error creating partnership account. Error: {}'.format(e))
return -1
@classmethod
def update(cls, id, name, billing_type):
"""
Update the partnership account's details.
:return: bool
"""
account = PartnershipAccount.query.filter(PartnershipAccount.id == id).first()
if account is not None:
account.name = name
if billing_type is not None and billing_type in ['partnership', 'account', 'invoice']:
account.billing_type = billing_type
db.session.commit()
return True
else:
return False
@classmethod
<<<<<<< HEAD
def api_update(cls, id, partnership_id, name, is_active, partner_account_code, description,
safety_information, address_1, address_2, city, state, zip_code, country, timezone,
business_type, users=None):
=======
def api_update(cls, id, partnership_id, name, is_active, partner_account_code,
partner_account_credit_service_provider, users=None):
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
"""
Update the partnership account's details.
:return: bool
"""
account = PartnershipAccount.query \
.filter(and_(PartnershipAccount.id == id, PartnershipAccount.partnership_id == partnership_id)).first()
if account is not None:
if name is not None and name != '':
account.name = name
if is_active is not None:
account.active = is_active
if partner_account_code is not None and partner_account_code != '':
account.partner_account_code = partner_account_code
<<<<<<< HEAD
if description is not None:
account.description = description
if safety_information is not None:
account.safety_information = safety_information
if address_1 is not None:
account.address_1 = address_1
if address_2 is not None:
account.address_2 = address_2
if city is not None:
account.city = city
if state is not None:
account.state = state
if zip_code is not None:
account.zip_code = zip_code
if country is not None:
account.country = country
if timezone is not None:
account.timezone = timezone
if business_type is not None:
account.business_type = business_type
=======
if partner_account_credit_service_provider is not None and partner_account_credit_service_provider != '':
partner_account_credit_service_provider_lower = partner_account_credit_service_provider.lower()
existing_credit_tie = (PartnershipAccountCreditTie.query
.filter(and_(PartnershipAccountCreditTie.partnership_account_id == id,
PartnershipAccountCreditTie.service_provider ==
partner_account_credit_service_provider_lower)).first())
if not existing_credit_tie:
new_credit_sp = PartnershipAccountCreditTie(
service_provider=partner_account_credit_service_provider_lower,
active=True,
partnership_account_id=id,
product_type='prequalify',
equifax_enabled=True
)
db.session.add(new_credit_sp)
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
if users is not None:
for usr in users:
new_user = User(
firstname=usr['firstname'],
lastname=usr['lastname'],
email=usr['email'].lower(),
phonenumber=format_phone_number(str(usr['phonenumber'])),
password=usr['password'],
role=usr['role'],
partnership_account_id=account.id,
partnership_id=account.partnership_id,
company=account.name,
tos_agreement=False
)
db.session.add(new_user)
<<<<<<< HEAD
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
db.session.flush()
db.session.commit()
return True
else:
return False
@classmethod
def search(cls, query):
"""
Search a resource by 1 or more fields.
:param query: Search query
:type query: str
:return: SQLAlchemy filter
"""
if not query:
return text('')
search_query = '%{0}%'.format(query)
search_chain = (PartnershipAccount.name.ilike(search_query))
# return or_(*search_chain)
return search_chain
@classmethod
def get_partnership_account_by_token(cls, api_token_id):
"""
Find a PartnershipAccount by their REST API token id.
"""
partnership_account = db.session.query(PartnershipAccount) \
.filter(and_(PartnershipAccount.api_token_id == api_token_id, PartnershipAccount.active == True)) \
.first()
if partnership_account:
return partnership_account
return None
@classmethod
def regenerate_api_token(cls, id):
"""
Regenerates the PartnershipAccount REST API token.
:return: api token
"""
partnership_account = db.session.query(PartnershipAccount) \
.filter(PartnershipAccount.id == id) \
.first()
if partnership_account is not None:
# Check if api token id already exists, if so, just regenerate
if partnership_account.api_token_id is not None and partnership_account.api_token_id > 0:
return ApiToken.regenerate_token(partnership_account.api_token_id)
# API token id does not exist, need to create a new one and regenerate the key
else:
new_token = ApiToken.create()
if new_token is not None and new_token > 0:
partnership_account.api_token_id = new_token
partnership_account.save()
db.session.commit()
return ApiToken.regenerate_token(new_token)
else:
return None
else:
# No partnership account found
return None
@classmethod
def find_by_token(cls, token):
"""
Find a PartnershipAccount by their REST API token.
"""
# token_hashes = db.session.query(PartnershipAccount.id, PartnershipAccount.api_token_hash).filter(
# PartnershipAccount.api_token_hash.isnot(None)
# ).all()
# for id, hash in token_hashes:
# if bcrypt.check_password_hash(hash, token):
# return PartnershipAccount.query.filter(PartnershipAccount.id == id).first()
return None
@classmethod
def total_calls_count(cls, paid):
total_calls = Lead.query.filter(Lead.partnership_account_id == paid).count()
return total_calls
@classmethod
# TODO: Review me
def total_inbound_calls_count(cls, paid):
total_calls = Lead.query.filter(and_(Lead.partnership_account_id == paid,
Lead.call_type == 'inbound')).count()
return total_calls
@classmethod
# TODO: Review me
def total_inbound_calls_count_for_phone(cls, paid, pnid):
total_calls = Lead \
.query \
.filter(and_(Lead.partnership_account_id == paid, Lead.call_type == 'inbound')) \
.filter(Lead.inbound_id == pnid) \
.count()
return total_calls
@classmethod
# TODO: Review me
def monthly_total_inbound_calls_count(cls, paid):
now = datetime.now()
year = now.year
month = now.month
total_calls = Lead.query.with_entities(Lead.id) \
.filter(and_(Lead.partnership_account_id == paid, Lead.call_type == 'inbound')) \
.filter(extract('year', Lead.created_on) == year) \
.filter(extract('month', Lead.created_on) == month) \
.count()
return total_calls
@classmethod
# TODO: Review me
def previous_total_inbound_calls_count(cls, paid):
now = datetime.now()
year = now.year
month = now.month
if month == 1:
year = now.year - 1
month = 12
else:
month = month - 1
total_calls = Lead.query.with_entities(Lead.id) \
.filter(and_(Lead.partnership_account_id == paid, Lead.call_type == 'inbound')) \
.filter(extract('year', Lead.created_on) == year) \
.filter(extract('month', Lead.created_on) == month) \
.count()
return total_calls
@classmethod
# TODO: Review me
def total_outbound_calls_count(cls, paid):
total_calls = db.session.query(Lead.id) \
.filter(and_(Lead.partnership_account_id == paid, Lead.call_type == 'outbound')) \
.distinct() \
.count()
return total_calls
@classmethod
# TODO: Review me
def total_outbound_calls_count_for_phone(cls, paid, pnid):
total_calls = db.session.query(Lead.id) \
.filter(and_(Lead.partnership_account_id == paid, Lead.call_type == 'outbound')) \
.filter(Lead.inbound_id == pnid) \
.distinct() \
.count()
return total_calls
@classmethod
# TODO: Review me
def monthly_total_outbound_calls_count(cls, paid):
now = datetime.now()
year = now.year
month = now.month
total_calls = db.session.query(Lead).with_entities(Lead.id) \
.filter(and_(Lead.partnership_account_id == paid, Lead.call_type == 'outbound')) \
.filter(extract('year', Lead.created_on) == year) \
.filter(extract('month', Lead.created_on) == month) \
.distinct() \
.count()
return total_calls
@classmethod
# TODO: Review me
def previous_total_outbound_calls_count(cls, paid):
now = datetime.now()
year = now.year
month = now.month
if month == 1:
year = now.year - 1
month = 12
else:
month = month - 1
total_calls = Lead.query.with_entities(Lead.id) \
.filter(and_(Lead.partnership_account_id == paid, Lead.call_type == 'outbound')) \
.filter(extract('year', Lead.created_on) == year) \
.filter(extract('month', Lead.created_on) == month) \
.count()
return total_calls
@classmethod
def monthly_minute_usage(cls, paid):
now = datetime.now()
year = now.year
month = now.month
partnership_account_month_minutes = Lead.query.with_entities(Lead.duration) \
.filter(Lead.partnership_account_id == paid) \
.filter(extract('year', Lead.created_on) == year) \
.filter(extract('month', Lead.created_on) == month) \
.all()
new_call_duration = [i.duration for i in partnership_account_month_minutes]
call_duration_list = list()
for duration in new_call_duration:
if not duration:
duration_zero = float(0)
call_duration_list.append(duration_zero)
else:
float_duration = math.ceil(float(duration) / 60.0)
call_duration_list.append(float_duration)
month_minutes = int(sum(call_duration_list))
return month_minutes
@classmethod
def previous_month_minute_usage(cls, paid):
now = datetime.now()
year = now.year
month = now.month
if month == 1:
year = now.year - 1
month = 12
else:
month = month - 1
partnership_account_previous_month_minutes = Lead.query.with_entities(Lead.duration) \
.filter(Lead.partnership_account_id == paid) \
.filter(extract('year', Lead.created_on) == year) \
.filter(extract('month', Lead.created_on) == month).all()
previous_new_call_duration = [i.duration for i in partnership_account_previous_month_minutes]
previous_call_duration_list = list()
for previous_duration in previous_new_call_duration:
if not previous_duration:
previous_duration_zero = float(0)
previous_call_duration_list.append(previous_duration_zero)
else:
previous_float_duration = math.ceil(float(previous_duration) / 60.0)
previous_call_duration_list.append(previous_float_duration)
previous_month_minutes = int(sum(previous_call_duration_list))
return previous_month_minutes
@classmethod
def total_minute_usage(cls, paid):
partnership_account_total_minutes = Lead.query.with_entities(Lead.duration) \
.filter(Lead.partnership_account_id == paid).all()
new_total_duration = [i.duration for i in partnership_account_total_minutes]
total_duration_list = list()
for total in new_total_duration:
if not total:
total_zero = float(0)
total_duration_list.append(total_zero)
else:
total_float_duration = math.ceil(float(total) / 60.0)
total_duration_list.append(total_float_duration)
total_minutes = int(sum(total_duration_list))
return total_minutes
@classmethod
# TODO: Review me
def total_active_phonenumbers(cls, paid):
from buyercall.blueprints.phonenumbers.models import Phone
total_phonenumbers = Phone.query.filter(
and_(Phone.partnership_account_id == paid, Phone.is_deactivated == False)
).count()
return total_phonenumbers
@classmethod
# TODO: Review me
def total_priority_phonenumbers(cls, paid):
from buyercall.blueprints.phonenumbers.models import Phone
total_phonenumbers = Phone.query.filter(
Phone.partnership_account_id == paid
).filter(Phone.type == 'priority', Phone.is_deactivated == '0').count()
return total_phonenumbers
@classmethod
# TODO: Review me
def total_tracking_phonenumbers(cls, paid):
from buyercall.blueprints.phonenumbers.models import Phone
total_phonenumbers = Phone.query.filter(
Phone.partnership_account_id == paid
).filter(Phone.type == 'tracking', Phone.is_deactivated == '0').count()
return total_phonenumbers
@classmethod
# TODO: Review me
def total_mobile_phonenumbers(cls, paid):
from buyercall.blueprints.phonenumbers.models import Phone
total_phonenumbers = Phone.query.filter(
Phone.partnership_account_id == paid
).filter(Phone.type == 'mobile', Phone.is_deactivated == '0').count()
return total_phonenumbers
@classmethod
# TODO: Review me
def total_messages(cls, paid):
total_messages_count = Message.query.filter(Message.partnership_account_id == paid) \
.distinct() \
.count()
return total_messages_count
@classmethod
# TODO: Review me
def total_inbound_messages(cls, paid):
total_messages = Message.query \
.filter(Message.partnership_account_id == paid) \
.filter(or_(Message.direction == 'in', Message.direction == 'inbound')) \
.count()
return total_messages
@classmethod
# TODO: Review me
def total_inbound_messages_for_phone(cls, paid, pnid):
total_messages = Message.query \
.filter(Message.partnership_account_id == paid) \
.filter(or_(Message.direction == 'in', Message.direction == 'inbound')) \
.filter(Message.inbound_id == pnid) \
.distinct() \
.count()
return total_messages
@classmethod
# TODO: Review me
def total_monthly_inbound_messages(cls, paid):
now = datetime.now()
year = now.year
month = now.month
total_messages = Message.query \
.filter(Message.partnership_account_id == paid) \
.filter(or_(Message.direction == 'in', Message.direction == 'inbound')) \
.filter(extract('year', Message.created_on) == year) \
.filter(extract('month', Message.created_on) == month) \
.count()
return total_messages
@classmethod
# TODO: Review me
def previous_total_monthly_inbound_messages(cls, paid):
now = datetime.now()
year = now.year
month = now.month
if month == 1:
year = now.year - 1
month = 12
else:
month = month - 1
total_messages = Message.query \
.filter(Message.partnership_account_id == paid) \
.filter(or_(Message.direction == 'in', Message.direction == 'inbound')) \
.filter(extract('year', Message.created_on) == year) \
.filter(extract('month', Message.created_on) == month) \
.count()
return total_messages
@classmethod
# TODO: Review me
def total_outbound_messages(cls, paid):
total_messages = Message.query \
.filter(Message.partnership_account_id == paid) \
.filter(or_(Message.direction == 'out', Message.direction == 'outbound')) \
.distinct() \
.count()
return total_messages
@classmethod
# TODO: Review me
def total_outbound_messages_for_phone(cls, paid, pnid):
total_messages = Message.query \
.filter(Message.partnership_account_id == paid) \
.filter(or_(Message.direction == 'out', Message.direction == 'outbound')) \
.filter(Message.inbound_id == pnid) \
.distinct() \
.count()
return total_messages
@classmethod
# TODO: Review me
def total_monthly_outbound_messages(cls, paid):
now = datetime.now()
year = now.year
month = now.month
total_messages = Message.query \
.filter(Message.partnership_account_id == paid) \
.filter(or_(Message.direction == 'out', Message.direction == 'outbound')) \
.filter(extract('year', Message.created_on) == year) \
.filter(extract('month', Message.created_on) == month) \
.distinct() \
.count()
return total_messages
@classmethod
# TODO: Review me
def previous_total_monthly_outbound_messages(cls, paid):
now = datetime.now()
year = now.year
month = now.month
if month == 1:
year = now.year - 1
month = 12
else:
month = month - 1
total_messages = Message.query \
.filter(Message.partnership_account_id == paid) \
.filter(or_(Message.direction == 'out', Message.direction == 'outbound')) \
.filter(extract('year', Message.created_on) == year) \
.filter(extract('month', Message.created_on) == month) \
.distinct() \
.count()
return total_messages
@classmethod
def partnership_account_appointment_availability(cls, partnership_account_id, appointment_type, date, start_time):
"""
Check if a partnership account is available for a specific date and time
:param partnership_account_id: Account id
:param appointment_type: The request appointment type
:param date: The request appointment date
:param start_time: The request appointment start time
:type partnership_account_id: int
:type appointment_type: string
:type date: string
:type start_time: string
:return: True
"""
# Retrieve the user record
account = cls.query.filter(cls.id == partnership_account_id).first()
format_date = datetime.strptime(date, "%Y-%m-%d")
date_weekday = (format_date.weekday() + 1) % 7
start_time = convert_to_deltatime(start_time)
end_time = start_time + timedelta(minutes=account.appointment_interval)
format_start_time = datetime.strptime(str(start_time), "%H:%M:%S")
format_end_time = datetime.strptime(str(end_time), "%H:%M:%S")
final_start_time = format_start_time.time()
final_end_time = format_end_time.time()
requested_appointment = {'date': str(format_date),
'weekday': date_weekday,
'start_time': str(final_start_time)[:-3],
'end_time': str(final_end_time)[:-3]}
available_slots = cls.partnership_account_available_appointment_slots(account.id, appointment_type, date)
if requested_appointment in available_slots:
return True
else:
return False
@classmethod
def partnership_account_available_appointment_slots(cls, partnership_account_id, appointment_type, date=None):
"""
Retrieve a list of start and end time appointment slots for a specific date a partnership account
:param partnership_account_id: Account id
:param appointment_type: The appointment type in question
:param date: The date in question
:type partnership_account_id: int
:type appointment_type: string
:type date: string
:return: list of appointment slot dictionaries for a specific date and partnership account
"""
# Find the user based on user id provided
account = cls.query.filter(and_(cls.id == partnership_account_id,
cls.active.is_(True),
cls.appointment_enabled.is_(True))).first()
# Set general value for appointment_type when not provided
if appointment_type is None:
appointment_type = 'general'
# Set the appointment type variable
if appointment_type == "service":
appointment_type_count = account.appointment_service_slot_count
elif appointment_type == 'general':
appointment_type_count = account.appointment_general_slot_count
else:
appointment_type_count = 0
# Set or create the date parameters
date_today = datetime.strptime(str(datetime_date.today()), "%Y-%m-%d")
account_timezone = account.timezone
tz = pytz.timezone(account_timezone)
time_now = datetime.now(tz)
account_time_now = time_now.strftime('%H:%M:%S')
if date:
format_date = datetime.strptime(date, "%Y-%m-%d")
future_date = str(format_date + relativedelta(months=+2))[:-9]
format_future_date = datetime.strptime(future_date, "%Y-%m-%d")
else:
# If no date is provided use today's date
format_date = date_today
future_date = str(format_date + relativedelta(months=+2))[:-9]
format_future_date = datetime.strptime(future_date, "%Y-%m-%d")
try:
if account:
# Return all the dates between request/current date and the future date allow with its day of the week
dates_with_weekdays = []
start_date = format_date
while start_date <= format_future_date:
weekday = (start_date.weekday() + 1) % 7
date_and_day = {'date': start_date, 'weekday': weekday}
dates_with_weekdays.append(date_and_day)
start_date += relativedelta(days=1)
# Return all user available dates and time availability based on their schedule weekdays
dates_with_schedules = []
# Check to verify if the user is using a schedule and use start and end times from schedule
if account.operating_hours.count() != 0:
for date_and_day in dates_with_weekdays:
for var_day in account.operating_hours:
if var_day.day == date_and_day['weekday'] and var_day.is_active \
and var_day.operating_type == appointment_type:
schedule_start_time = var_day.available_from
schedule_end_time = var_day.available_to
available_days = {'date': date_and_day['date'],
'weekday': date_and_day['weekday'],
'schedule_start_time': schedule_start_time,
'schedule_end_time': schedule_end_time}
dates_with_schedules.append(available_days)
# Else if the user schedule is not set than use all dates with all hours in day
else:
for date_and_day in dates_with_weekdays:
schedule_start_time = '00:00:00'
schedule_end_time = '23:00:00'
available_days = {'date': date_and_day['date'],
'weekday': date_and_day['weekday'],
'schedule_start_time': schedule_start_time,
'schedule_end_time': schedule_end_time}
dates_with_schedules.append(available_days)
# Get current list of appointments for an account between a specific date and 2 months out
appointments = Appointment.query \
.filter(and_(Appointment.partnership_account_id == account.id,
Appointment.is_deactivated.is_(False),
Appointment.appointment_type == appointment_type,
Appointment.appointment_date >= format_date,
Appointment.appointment_date <= format_future_date)).all()
# Identify time slots for appointments that's already booked
unavailable_slots = []
for appointment in appointments:
for appointment_slot in appointment.appointment_slot:
appointment_time_slot = {'date': str(appointment.appointment_date),
'weekday': (appointment.appointment_date.weekday() + 1) % 7,
'start_time': appointment_slot.start_time,
'end_time': appointment_slot.end_time}
# Get the count for an appointment for a specific date and time
appointment_count = Appointment.appointment_count(account.id,
str(appointment.appointment_date),
appointment_slot.start_time,
appointment.appointment_type)
if appointment_count >= appointment_type_count \
and appointment_time_slot not in unavailable_slots:
unavailable_slots.append(appointment_time_slot)
# Return all available time slots for the date range 3 months out ignoring already booked slots
available_slots = []
for schedule_date in dates_with_schedules:
schedule_start_time = schedule_date['schedule_start_time']
while schedule_start_time < schedule_date['schedule_end_time'] \
and schedule_start_time < '23:00:00':
start_time = convert_to_deltatime(schedule_start_time[:-3])
end_time = start_time + timedelta(minutes=account.appointment_interval)
format_start_time = datetime.strptime(str(start_time), "%H:%M:%S")
format_end_time = datetime.strptime(str(end_time), "%H:%M:%S")
final_start_time = format_start_time.time()
final_end_time = format_end_time.time()
slot = {'date': str(schedule_date['date']),
'weekday': schedule_date['weekday'],
'start_time': str(final_start_time)[:-3],
'end_time': str(final_end_time)[:-3]}
if slot not in unavailable_slots:
if str(slot['date']) == str(date_today) \
and slot['start_time'] < account_time_now:
pass
else:
available_slots.append(slot)
schedule_start_time = str(final_end_time)
return available_slots
except Exception:
log.error('User available appointment slots error message: {}'.format(traceback.format_exc()))
@hybrid_property
def api_token_hash(self):
"""
Returns the REST API token for this partnership account.
"""
token = db.session.query(ApiToken.api_token_hash) \
.filter(ApiToken.id == self.api_token_id).first()
if token is not None:
return token
else:
return None
@hybrid_property
def has_active_subscription(self):
if not self.subscription:
return False
return self.subscription.status == 'active'
@has_active_subscription.expression
def has_active_subscription(cls):
if not cls.subscription:
return False
return cls.subscription.status == 'active'
@property
def created_datetime(self):
""" Return the date/time this partnership account occurred
"""
return self.created_on.strftime('%Y-%m-%d %H:%M:%S')
@property
def updated_datetime(self):
""" Return the date/time this partnership account record was updated
"""
return self.updated_on.strftime('%Y-%m-%d %H:%M:%S')
@property
def is_active(self):
""" Return the status of partnership account
"""
return self.active
@classmethod
def phone_number_usage(cls, paid, pnid):
try:
inbound_call_count_result = cls.total_inbound_calls_count_for_phone(paid, pnid)
outbound_call_count_result = cls.total_outbound_calls_count_for_phone(paid, pnid)
inbound_message_count_result = cls.total_inbound_messages_for_phone(paid, pnid)
outbound_message_count_result = cls.total_outbound_messages_for_phone(paid, pnid)
return jsonify(
inbound_call_count=inbound_call_count_result,
outbound_call_count=outbound_call_count_result,
inbound_message_count=inbound_message_count_result,
outbound_message_count=outbound_message_count_result
)
except Exception as e:
log.error(traceback.format_exc())
return ''
<<<<<<< HEAD
class PartnershipAccountOperatingHours(ResourceMixin, db.Model):
__tablename__ = 'partnership_account_operating_hours'
id = db.Column(db.Integer, primary_key=True)
sid = db.Column(UUID(as_uuid=True), unique=True, default=uuid.uuid4, index=True)
partnership_account_id = db.Column(
db.Integer,
db.ForeignKey(
'partnership_accounts.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=False
)
operating_type = db.Column(db.String(64), nullable=False, server_default='general')
is_active = db.Column(db.Boolean, nullable=False)
day = db.Column(db.Integer, index=True, nullable=False)
available_from = db.Column(
db.String(8), nullable=False, server_default='08:00:00'
)
available_to = db.Column(
db.String(8), nullable=False, server_default='17:00:00'
)
is_all_hours = db.Column(db.Boolean, nullable=True)
def __init__(self, day, available_from, available_to, is_active, partnership_account_id, operating_type, is_all_hours):
self.day = day
self.available_from = available_from
self.available_to = available_to
self.is_active = is_active
self.partnership_account_id = partnership_account_id
self.operating_type = operating_type
self.is_all_hours = is_all_hours
@classmethod
def create(cls, *days):
"""
Return whether the partnership account operating hours was created successfully.
:return: bool
"""
for day in days:
db.session.add(PartnershipAccountOperatingHours(**day))
db.session.commit()
return True
@classmethod
def update(cls, operating_id, available_from, available_to, is_active,
partnership_account_id, operating_type='general'):
db.session.query(PartnershipAccountOperatingHours).filter_by(id=operating_id).update(
{"is_active": is_active,
"available_from": available_from,
"available_to": available_to
})
db.session.commit()
@classmethod
def api_update(cls, operating_id, available_from, available_to, is_active,
partnership_account_id):
try:
operating_hours = PartnershipAccountOperatingHours.query.filter(
and_(PartnershipAccountOperatingHours.id == operating_id,
PartnershipAccountOperatingHours.partnership_account_id == partnership_account_id
)
).first()
if operating_hours is not None:
if available_from is not None:
operating_hours.available_from = available_from
if available_to is not None:
operating_hours.available_to = available_to
if is_active is not None:
operating_hours.is_active = is_active
db.session.commit()
return True
else:
return False
except Exception as e:
log.error('Error updating partnership account operating hours. Error: {}'.format(e.message))
return False
@classmethod
def deactivate(cls, partnership_account_id):
account_found = db.session.query(PartnershipAccount) \
.filter(PartnershipAccount.id == partnership_account_id).first()
if account_found is not None:
operating_hours = db.session.query(PartnershipAccountOperatingHours) \
.filter(PartnershipAccountOperatingHours.partnership_account_id == account_found.id).all()
for operating_hour in operating_hours:
operating_hour.is_active = False
db.session.commit()
return True
else:
return False
@classmethod
def get_by_account_id(cls, partnership_account_id):
operating_hours = db.session.query(PartnershipAccountOperatingHours) \
.filter(PartnershipAccountOperatingHours.partnership_account_id == partnership_account_id).all()
return operating_hours if operating_hours else []
@classmethod
def get_general_by_account(cls, partnership_account_id):
operating_hours = db.session.query(cls) \
.filter(cls.partnership_account_id == partnership_account_id, cls.operating_type == 'general').all()
return operating_hours if operating_hours else []
@classmethod
def get_service_by_account(cls, partnership_account_id):
operating_hours = db.session.query(cls) \
.filter(cls.partnership_account_id == partnership_account_id, cls.operating_type == 'service').all()
return operating_hours if operating_hours else []
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
class Partnership(ResourceMixin, db.Model):
__tablename__ = 'partnerships'
id = db.Column(db.Integer, primary_key=True)
sid = db.Column(UUID(as_uuid=True), unique=True, default=uuid.uuid4, index=True)
name = db.Column(db.String(255), index=True, nullable=False,
server_default='')
active = db.Column('is_active', db.Boolean(), nullable=False,
server_default='1')
account_invitation_url_token = db.Column(
db.String(255),
index=True,
nullable=False,
server_default=''
)
subscription_id = db.Column(db.Integer, db.ForeignKey('subscriptions.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=True)
users = db.relationship(User, backref="partnership")
partnership_accounts = db.relationship(PartnershipAccount, backref="partnership")
issues = db.relationship(Issue, backref="partnership")
invoices = db.relationship(Invoice, backref='partnership')
logo = db.Column(db.String(2000), index=True, nullable=False,
server_default='')
alternative_logo = db.Column(db.String(512), index=True, nullable=False,
server_default='')
logo_small = db.Column(db.String(2000), index=True, nullable=False,
server_default='')
alternative_logo_small = db.Column(db.String(512), index=True, nullable=False,
server_default='')
default_billing_type = db.Column(db.Enum(*BILLING_TYPE, name='billing_types'),
index=True, nullable=False, server_default='partnership')
default_provider = db.Column(
db.String(10), nullable=False, server_default='twilio',
index=True,
)
api_token_id = db.Column(
db.Integer,
db.ForeignKey(
'api_tokens.id',
onupdate='CASCADE',
ondelete='CASCADE'
),
index=True, nullable=True
)
partner_url = db.Column(
db.String(256), nullable=False, server_default='',
index=True,
)
email_sender = db.Column(
db.String(64), nullable=False, server_default='',
index=True,
)
partner_type = db.Column(
db.String(256), nullable=False, server_default='general',
index=True,
)
business_type = db.Column(
db.String(128), nullable=False, server_default='general',
index=True
)
<<<<<<< HEAD
primary_color = db.Column(
db.String(10), nullable=False, server_default='#2a3042'
)
is_expanded_menu = db.Column('is_expanded_menu', db.Boolean(), nullable=False,
server_default='1')
dkim_records = db.Column(ARRAY(db.String(128)))
domain_record = db.Column(
db.String(128), nullable=False, server_default=''
)
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
operational_number = db.Column(
db.String(32), nullable=False, server_default='',
index=False,
)
custom_styles = db.Column(
db.String(128), nullable=False, server_default='',
<<<<<<< HEAD
index=False
)
=======
index=False,
)
is_2fa_email_enabled = db.Column(db.Boolean(), nullable=False,
server_default='0')
is_2fa_sms_enabled = db.Column(db.Boolean(), nullable=False,
server_default='1')
is_2fa_enforced = db.Column(db.Boolean(), nullable=False,
server_default='0')
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
@classmethod
def search(cls, query):
"""
Search a resource by 1 or more fields.
:param query: Search query
:type query: str
:return: SQLAlchemy filter
"""
if not query:
return text('')
search_query = '%{0}%'.format(query)
search_chain = (Partnership.name.ilike(search_query))
# return or_(*search_chain)
return search_chain
@classmethod
def get_name(cls, pid):
obj = cls.query.filter(cls.id == pid).first()
return obj.name if obj else None
@classmethod
def get_by_invitation_token(cls, token=None):
return cls.query.filter(cls.account_invitation_url_token == token).first() if token else None
@classmethod
def get_partnership_by_token(cls, api_token_id):
"""
Find a Partnership by their REST API token id.
"""
partnership = db.session.query(Partnership) \
.filter(and_(Partnership.api_token_id == api_token_id, Partnership.active == True)) \
.first()
if partnership is not None:
return partnership
else:
return None
@classmethod
def regenerate_api_token(cls, id):
"""
Regenerates the Partnership REST API token.
:return: api token
"""
partnership = db.session.query(Partnership) \
.filter(Partnership.id == id) \
.first()
if partnership is not None:
# Check if api token id already exists, if so, just regenerate
if partnership.api_token_id is not None and partnership.api_token_id > 0:
return ApiToken.regenerate_token(partnership.api_token_id)
# API token id does not exist, need to create a new one and regenerate the key
else:
new_token = ApiToken.create()
if new_token is not None and new_token > 0:
partnership.api_token_id = new_token
partnership.save()
db.session.commit()
return ApiToken.regenerate_token(new_token)
else:
return None
else:
# No partnership found
return None
@classmethod
def get_partnership_accounts(cls):
"""
Find and return a list of all the partnership accounts linked to this partnership.
"""
partnership_accounts = (db.session.query(PartnershipAccount)) \
.filter(and_(PartnershipAccount.partnership_id == cls.id,
PartnershipAccount.active == True)) \
.order_by(PartnershipAccount.name) \
.all()
return partnership_accounts
@classmethod
def get_partnership_account(cls, paid):
"""
Find and return a partnership accounts linked to this partnership based on partnership account id.
"""
partnership_account = (db.session.query(PartnershipAccount)) \
.filter(and_(PartnershipAccount.partnership_id == cls.id,
PartnershipAccount.active == True,
PartnershipAccount.id == paid)).first()
return partnership_account
@hybrid_property
def api_token_hash(self):
"""
Returns the REST API token for this partnership account.
"""
token = db.session.query(ApiToken.api_token_hash) \
.filter(ApiToken.id == self.api_token_id) \
.first()
if token is not None:
return token
else:
return None
@hybrid_property
def has_active_subscription(self):
if not self.subscription:
return False
return self.subscription.status == 'active'
@hybrid_property
def billing_type(self):
return self.default_billing_type
@classmethod
def update_business_type(cls, partnership_id, business_type):
"""
Updates the busines type of all related partnership accounts.
"""
if partnership_id and business_type:
update_stmt = update(PartnershipAccount) \
.where(PartnershipAccount.partnership_id == partnership_id) \
.values(business_type=business_type)
db.session.execute(update_stmt)
db.session.commit()
@classmethod
def close_account(cls, pid):
"""
Deactivates the account and it's accounts and users
"""
try:
partnership = cls.query.filter(cls.sid == pid).first()
partnership.active = False
partnership.save()
users = partnership.users
for u in users:
u.active = False
u.is_deactivated = True
u.deactivated_on = datetime.now()
u.save()
partnership_accounts = partnership.partnership_accounts
for pa in partnership_accounts:
pa.active = False
pa.save()
return True
except Exception as e:
print(e)
return False
@classmethod
def get_by_partner_url(cls, purl):
return cls.query.filter(cls.partner_url == purl).first()
@classmethod
def get_by_email(cls, email):
return cls.query.filter(cls.email_sender == email).first()
class PartnershipCpaasProviders(ResourceMixin, db.Model):
__tablename__ = 'partnership_cpaas_providers'
id = db.Column(db.Integer, primary_key=True)
cpaas_provider_name = db.Column(db.String(32), index=True, nullable=False, server_default='')
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1')
partnership_id = db.Column(db.Integer, db.ForeignKey('partnerships.id',
onupdate='CASCADE',
ondelete='CASCADE'), index=True, nullable=False)
cpaas_default_provider = db.Column('is_default_provider', db.Boolean(), nullable=False, server_default='0')
cpaas_account_id = db.Column(db.String(128), index=True, nullable=False, server_default='')
cpaas_api_token = db.Column(db.String(128), index=True, nullable=False, server_default='')
cpaas_api_secret = db.Column(db.String(128), index=True, nullable=False, server_default='')
cpaas_user_id = db.Column(db.String(128), index=True, nullable=False, server_default='')
cpaas_api_username = db.Column(db.String(128), index=True, nullable=False, server_default='')
cpaas_api_password = db.Column(db.String(128), index=True, nullable=False, server_default='')
cpaas_site_id = db.Column(db.String(128), index=True, nullable=False, server_default='')
cpaas_location_id = db.Column(db.String(64), index=True, nullable=False, server_default='')
cpaas_sms_application_id = db.Column(db.String(64), index=True, nullable=False, server_default='')
cpaas_voice_application_id = db.Column(db.String(64), index=True, nullable=False, server_default='')
cpaas_caller_id = db.Column(db.String(12), index=True, nullable=False, server_default='')
cpaas_cnam_password = db.Column(db.String(64), index=True, nullable=False, server_default='')
@classmethod
def partnership_twilio_credentials(cls, paid):
"""
Find and return the partnership CPaaS twilio provider otherwise return default provider.
"""
twilio_as_provider = (db.session.query(cls)) \
.filter(cls.partnership_id == paid, cls.cpaas_provider_name == 'twilio', cls.active.is_(True)).first()
if twilio_as_provider is not None:
return twilio_as_provider
else:
default_twilio_as_provider = (db.session.query(cls)) \
.filter(cls.cpaas_default_provider.is_(True), cls.cpaas_provider_name == 'twilio',
cls.active.is_(True)).first()
return default_twilio_as_provider
@classmethod
def partnership_bandwidth_credentials(cls, paid):
"""
Find and return the partnership CPaaS bandwidth provider otherwise return default provider.
"""
twilio_as_provider = (db.session.query(cls)) \
.filter(cls.partnership_id == paid, cls.cpaas_provider_name == 'bandwidth', cls.active.is_(True)).first()
if twilio_as_provider is not None:
return twilio_as_provider
else:
default_twilio_as_provider = (db.session.query(cls)) \
.filter(cls.cpaas_default_provider.is_(True), cls.cpaas_provider_name == 'bandwidth',
cls.active.is_(True)).first()
return default_twilio_as_provider
class PartnershipCpaasPhoneNumberSubscriptions(ResourceMixin, db.Model):
__tablename__ = 'partnership_cpaas_phonenumber_subscriptions'
id = db.Column(db.Integer, primary_key=True)
cpaas_provider_name = db.Column(db.String(32), index=True, nullable=False, server_default='')
partnership_id = db.Column(db.Integer, db.ForeignKey('partnerships.id',
onupdate='CASCADE',
ondelete='CASCADE'), index=True, nullable=False)
order_type = db.Column(db.String(32), index=True, nullable=False, server_default='')
subscription_id = db.Column(db.String(128), index=True, nullable=False, server_default='')
callback_url = db.Column(db.String(128), index=True, nullable=False, server_default='')
@classmethod
def partnership_bandwidth_phonenumber_subscription(cls, paid):
"""
Find and return the subscription for bandwidth phone number order
"""
partnership_id = paid
return partnership_id
class PartnershipCreditTie(ResourceMixin, db.Model):
__tablename__ = 'partnership_credit_tie'
id = db.Column(db.Integer, primary_key=True)
service_provider = db.Column(db.String(128), index=True, nullable=False, server_default='')
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1')
partnership_id = db.Column(db.Integer, db.ForeignKey('partnerships.id',
onupdate='CASCADE',
ondelete='CASCADE'), index=True, nullable=False)
product_type = db.Column(db.String(128), index=True, nullable=False, server_default='')
api_account = db.Column(db.String(256), index=True, nullable=False, server_default='')
api_username = db.Column(db.String(256), index=True, nullable=False, server_default='')
api_password = db.Column(db.String(256), index=True, nullable=False, server_default='')
experian_enabled = db.Column('experian_enabled', db.Boolean(), nullable=False, server_default='0')
transunion_enabled = db.Column('transunion_enabled', db.Boolean(), nullable=False, server_default='0')
equifax_enabled = db.Column('equifax_enabled', db.Boolean(), nullable=False, server_default='0')
@classmethod
def partner_finserv_credit_info(cls, pid, product_type):
"""
Find and return the partnership account's Finserv credit credentials.
"""
finserv_credit_as_provider = (db.session.query(cls)) \
.filter(cls.partnership_id == pid,
cls.service_provider == 'Finserv',
cls.product_type == product_type,
cls.active.is_(True)).first()
if finserv_credit_as_provider is not None:
return finserv_credit_as_provider
else:
return None
class PartnershipAccountCounts(ResourceMixin, db.Model):
<<<<<<< HEAD
__tablename__ = 'partnership_account_counts'
partnership_account_id = db.Column(db.Integer, db.ForeignKey('partnership_accounts.id'),
primary_key=True, index=True, nullable=False)
contact_count = db.Column(db.Integer, nullable=True)
call_count = db.Column(db.Integer, nullable=True)
form_lead_count = db.Column(db.Integer, nullable=True)
message_count = db.Column(db.Integer, nullable=True)
=======
__tablename__ = 'partnership_account_counts'
partnership_account_id = db.Column(db.Integer, db.ForeignKey('partnership_accounts.id'),
primary_key=True, index=True, nullable=False)
contact_count = db.Column(db.Integer, nullable=True)
call_count = db.Column(db.Integer, nullable=True)
form_lead_count = db.Column(db.Integer, nullable=True)
message_count = db.Column(db.Integer, nullable=True)
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b