1
|
|
|
# Copyright 2013 Mathias WOLFF |
2
|
|
|
# This file is part of pyfreebilling. |
3
|
|
|
# |
4
|
|
|
# pyfreebilling is free software: you can redistribute it and/or modify |
5
|
|
|
# it under the terms of the GNU General Public License as published by |
6
|
|
|
# the Free Software Foundation, either version 3 of the License, or |
7
|
|
|
# (at your option) any later version. |
8
|
|
|
# |
9
|
|
|
# pyfreebilling is distributed in the hope that it will be useful, |
10
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
11
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12
|
|
|
# GNU General Public License for more details. |
13
|
|
|
# |
14
|
|
|
# You should have received a copy of the GNU General Public License |
15
|
|
|
# along with pyfreebilling. If not, see <http://www.gnu.org/licenses/> |
16
|
|
|
|
17
|
|
|
from django.db import models |
18
|
|
|
from django.db.models import permalink, Sum, Avg, Count, Max, Min |
19
|
|
|
from django.core.validators import EMPTY_VALUES |
20
|
|
|
from django.core.exceptions import ValidationError |
21
|
|
|
from django.conf import settings |
22
|
|
|
from django.contrib.contenttypes.fields import GenericForeignKey |
23
|
|
|
from django.contrib.contenttypes.models import ContentType |
24
|
|
|
from django.contrib.contenttypes.fields import GenericRelation |
25
|
|
|
from django.utils import timezone |
26
|
|
|
from django.utils.translation import ugettext_lazy as _ |
27
|
|
|
from django.utils.html import format_html |
28
|
|
|
|
29
|
|
|
import datetime |
30
|
|
|
import qsstats |
31
|
|
|
import vatnumber |
32
|
|
|
|
33
|
|
|
from django_countries.fields import CountryField |
34
|
|
|
|
35
|
|
|
from netaddr import IPNetwork, AddrFormatError |
36
|
|
|
|
37
|
|
|
import re |
38
|
|
|
|
39
|
|
|
from .validators import validate_cidr, check_vat |
40
|
|
|
|
41
|
|
|
from pyfreebilling.switch.models import Domain |
42
|
|
|
|
43
|
|
|
|
44
|
|
|
class Company(models.Model): |
45
|
|
|
"""Company model.""" |
46
|
|
|
name = models.CharField(_(u'name'), |
47
|
|
|
max_length=200, |
48
|
|
|
unique=True) |
49
|
|
|
nickname = models.CharField(_(u'nickname'), |
50
|
|
|
max_length=50, |
51
|
|
|
blank=True, |
52
|
|
|
null=True) |
53
|
|
|
slug = models.SlugField(_(u'slug'), |
54
|
|
|
max_length=50, |
55
|
|
|
unique=True) |
56
|
|
|
about = models.CharField(_(u'about'), |
57
|
|
|
max_length=250, |
58
|
|
|
blank=True, |
59
|
|
|
null=True) |
60
|
|
|
phone_number = GenericRelation(u'PhoneNumber') |
61
|
|
|
email_address = GenericRelation(u'EmailAddress') |
62
|
|
|
web_site = GenericRelation(u'WebSite') |
63
|
|
|
street_address = GenericRelation(u'StreetAddress') |
64
|
|
|
account_number = models.IntegerField(_(u"Account number"), |
65
|
|
|
blank=True, |
66
|
|
|
null=True) |
67
|
|
|
vat = models.BooleanField(_(u"VAT Applicable / Not applicable"), |
68
|
|
|
default=False, |
69
|
|
|
help_text=_(u"if checked, VAT is applicable.")) |
70
|
|
|
vat_number = models.CharField(_(u"VAT number"), |
71
|
|
|
max_length=30, |
72
|
|
|
blank=True, |
73
|
|
|
validators=[check_vat]) |
74
|
|
|
vat_number_validated = models.BooleanField(_(u"VAT Vies Validated."), |
75
|
|
|
default=False, |
76
|
|
|
help_text=_(u"If on, it means that VAT is " |
77
|
|
|
u"validated through <a target='_blank' " |
78
|
|
|
u"href='http://ec.europa.eu/taxation_customs/vies/vatRequest.html'>Vies</a>.")) |
79
|
|
|
prepaid = models.BooleanField(_(u"Prepaid / Postpaid"), |
80
|
|
|
default=True, |
81
|
|
|
help_text=_(u"If checked, this account customer is prepaid.")) |
82
|
|
|
credit_limit = models.DecimalField(_(u'credit limit'), |
83
|
|
|
max_digits=12, |
84
|
|
|
decimal_places=4, |
85
|
|
|
default=0, |
86
|
|
|
help_text=_(u"Credit limit for postpaid account.")) |
87
|
|
|
low_credit_alert = models.DecimalField(_(u'low credit level alert'), |
88
|
|
|
max_digits=12, |
89
|
|
|
decimal_places=4, |
90
|
|
|
default="10", |
91
|
|
|
help_text=_(u"Low credit limit alert.")) |
92
|
|
|
low_credit_alert_sent = models.BooleanField(_(u"low credit alert ON"), |
93
|
|
|
default=False) |
94
|
|
|
account_blocked_alert_sent = models.BooleanField(_(u"Customer account blocked - low balance - ON"), |
95
|
|
|
default=False) |
96
|
|
|
email_alert = models.EmailField(_(u'alert email address'), |
97
|
|
|
blank=True, |
98
|
|
|
null=True) |
99
|
|
|
customer_balance = models.DecimalField(_(u'customer balance'), |
100
|
|
|
max_digits=12, |
101
|
|
|
decimal_places=6, |
102
|
|
|
default=0, |
103
|
|
|
help_text=_(u"Actual customer balance.")) |
104
|
|
|
supplier_balance = models.DecimalField(_(u'supplier balance'), |
105
|
|
|
max_digits=12, |
106
|
|
|
decimal_places=6, |
107
|
|
|
default=0, |
108
|
|
|
help_text=_(u"Actual supplier balance.")) |
109
|
|
|
max_calls = models.PositiveIntegerField(_(u'max simultaneous calls'), |
110
|
|
|
default=1, |
111
|
|
|
help_text=_(u"maximum simultaneous calls allowed for this customer account.")) |
112
|
|
|
calls_per_second = models.PositiveIntegerField( |
113
|
|
|
_(u'max calls per second'), |
114
|
|
|
default=10, |
115
|
|
|
help_text=_(u"maximum calls per seconds allowed for this customer account.") |
116
|
|
|
) |
117
|
|
|
BILLING_CYCLE_CHOICES = ( |
118
|
|
|
('w', _(u'weekly')), |
119
|
|
|
('m', _(u'monthly')), |
120
|
|
|
) |
121
|
|
|
billing_cycle = models.CharField( |
122
|
|
|
_(u'billing cycle'), |
123
|
|
|
max_length=10, |
124
|
|
|
choices=BILLING_CYCLE_CHOICES, |
125
|
|
|
default='m', |
126
|
|
|
help_text=_(u"billinng cycle for invoice generation.") |
127
|
|
|
) |
128
|
|
|
customer_enabled = models.BooleanField(_(u"Customer Enabled / Disabled"), |
129
|
|
|
default=True) |
130
|
|
|
supplier_enabled = models.BooleanField(_(u"Supplier Enabled / Disabled"), |
131
|
|
|
default=True) |
132
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
133
|
|
|
auto_now_add=True) |
134
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
135
|
|
|
auto_now=True) |
136
|
|
|
|
137
|
|
|
class Meta: |
138
|
|
|
db_table = 'company' |
139
|
|
|
app_label = 'pyfreebill' |
140
|
|
|
ordering = ('name',) |
141
|
|
|
verbose_name = _(u"Company") |
142
|
|
|
verbose_name_plural = _(u"Companies") |
143
|
|
|
|
144
|
|
|
def clean(self): |
145
|
|
|
if self.vat_number: |
146
|
|
|
try: |
147
|
|
|
vatnumber.check_vies(self.vat_number) |
148
|
|
|
except Exception, e: |
149
|
|
|
raise ValidationError(_(u"""Wrong VAT number - validation made throw VIES services. %s""")) % e |
150
|
|
|
|
151
|
|
|
def save(self, *args, **kwargs): |
152
|
|
|
if self.vat_number: |
153
|
|
|
try: |
154
|
|
|
self.vat_number_validated = vatnumber.check_vies(self.vat_number) |
155
|
|
|
except: |
156
|
|
|
self.vat_number_validated = False |
157
|
|
|
else: |
158
|
|
|
self.vat_number_validated = False |
159
|
|
|
|
160
|
|
|
super(Company, self).save(*args, **kwargs) |
161
|
|
|
|
162
|
|
|
def __unicode__(self): |
163
|
|
|
return u"%s" % self.name |
164
|
|
|
|
165
|
|
|
def colored_name(self): |
166
|
|
|
if self.customer_enabled == False and self.supplier_enabled == False: |
167
|
|
|
color = "red" |
168
|
|
|
elif self.customer_enabled == False and self.supplier_enabled == True: |
169
|
|
|
color = "orange" |
170
|
|
|
elif self.customer_enabled == True and self.supplier_enabled == False: |
171
|
|
|
color = "purple" |
172
|
|
|
else: |
173
|
|
|
color = "green" |
174
|
|
|
return " <span style=color:%s>%s</span>" % (color, self.name) |
175
|
|
|
colored_name.allow_tags = True |
176
|
|
|
|
177
|
|
|
def balance_history(self): |
178
|
|
|
html = '<span><a href="/extranet/pyfreebill/companybalancehistory/?company__id__exact={0}" class="btn btn-inverse btn-mini">Balance history <i class="icon-plus-sign"></i></a></span>' |
179
|
|
|
return format_html(html, (self.id)) |
180
|
|
|
balance_history.allow_tags = True |
181
|
|
|
balance_history.short_description = _(u'balance history') |
182
|
|
|
|
183
|
|
|
|
184
|
|
|
class Person(models.Model): |
185
|
|
|
"""Person model.""" |
186
|
|
|
first_name = models.CharField(_(u'first name'), |
187
|
|
|
max_length=100) |
188
|
|
|
last_name = models.CharField(_(u'last name'), |
189
|
|
|
max_length=200) |
190
|
|
|
middle_name = models.CharField(_(u'middle name'), |
191
|
|
|
max_length=200, |
192
|
|
|
blank=True, |
193
|
|
|
null=True) |
194
|
|
|
suffix = models.CharField(_(u'suffix'), |
195
|
|
|
max_length=50, |
196
|
|
|
blank=True, |
197
|
|
|
null=True) |
198
|
|
|
nickname = models.CharField(_(u'nickname'), |
199
|
|
|
max_length=100, |
200
|
|
|
blank=True) |
201
|
|
|
slug = models.SlugField(_(u'slug'), |
202
|
|
|
max_length=50, |
203
|
|
|
unique=True) |
204
|
|
|
title = models.CharField(_(u'title'), |
205
|
|
|
max_length=200, |
206
|
|
|
blank=True) |
207
|
|
|
company = models.ForeignKey(Company, |
208
|
|
|
blank=True, |
209
|
|
|
null=True) |
210
|
|
|
about = models.TextField(_(u'about'), |
211
|
|
|
blank=True) |
212
|
|
|
user = models.OneToOneField( |
213
|
|
|
settings.AUTH_USER_MODEL, |
214
|
|
|
on_delete=models.CASCADE, |
215
|
|
|
blank=True, |
216
|
|
|
null=True, |
217
|
|
|
verbose_name=_(u'user')) |
218
|
|
|
phone_number = GenericRelation('PhoneNumber') |
219
|
|
|
date_added = models.DateTimeField(_('date added'), |
220
|
|
|
auto_now_add=True) |
221
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
222
|
|
|
auto_now=True) |
223
|
|
|
|
224
|
|
|
class Meta: |
225
|
|
|
db_table = 'contacts_people' |
226
|
|
|
app_label = 'pyfreebill' |
227
|
|
|
ordering = ('last_name', 'first_name') |
228
|
|
|
verbose_name = _(u'person') |
229
|
|
|
verbose_name_plural = _(u'people') |
230
|
|
|
|
231
|
|
|
def __unicode__(self): |
232
|
|
|
return self.fullname |
233
|
|
|
|
234
|
|
|
@property |
235
|
|
|
def fullname(self): |
236
|
|
|
return u"%s %s" % (self.first_name, self.last_name) |
237
|
|
|
|
238
|
|
|
|
239
|
|
|
class Group(models.Model): |
240
|
|
|
"""Group model.""" |
241
|
|
|
name = models.CharField(_(u'name'), |
242
|
|
|
max_length=200, |
243
|
|
View Code Duplication |
unique=True) |
|
|
|
|
244
|
|
|
slug = models.SlugField(_(u'slug'), |
245
|
|
|
max_length=50, |
246
|
|
|
unique=True) |
247
|
|
|
about = models.TextField(_(u'about'), |
248
|
|
|
blank=True) |
249
|
|
|
people = models.ManyToManyField(Person, |
250
|
|
|
verbose_name=_(u'people'), |
251
|
|
|
blank=True) |
252
|
|
|
companies = models.ManyToManyField(Company, |
253
|
|
|
verbose_name=_(u'companies'), |
254
|
|
|
blank=True) |
255
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
256
|
|
|
auto_now_add=True) |
257
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
258
|
|
|
auto_now=True) |
259
|
|
|
|
260
|
|
|
class Meta: |
261
|
|
|
db_table = 'contacts_groups' |
262
|
|
|
app_label = 'pyfreebill' |
263
|
|
|
ordering = ('name',) |
264
|
|
|
verbose_name = _(u'group') |
265
|
|
|
verbose_name_plural = _(u'groups') |
266
|
|
|
|
267
|
|
|
def __unicode__(self): |
268
|
|
|
return u"%s" % self.name |
269
|
|
|
|
270
|
|
|
|
271
|
|
|
PHONE_LOCATION_CHOICES = ( |
272
|
|
|
('work', _(u'Work')), |
273
|
|
|
('mobile', _(u'Mobile')), |
274
|
|
|
('fax', _(u'Fax')), |
275
|
|
|
('pager', _(u'Pager')), |
276
|
|
|
('home', _(u'Home')), |
277
|
|
|
('other', _(u'Other')), |
278
|
|
|
) |
279
|
|
|
|
280
|
|
|
|
281
|
|
|
class PhoneNumber(models.Model): |
282
|
|
|
"""Phone Number model.""" |
283
|
|
|
content_type = models.ForeignKey( |
284
|
|
|
ContentType, |
285
|
|
View Code Duplication |
limit_choices_to={'app_label': 'contacts'}) |
|
|
|
|
286
|
|
|
object_id = models.IntegerField(db_index=True) |
287
|
|
|
content_object = GenericForeignKey('content_type', 'object_id') |
288
|
|
|
phone_number = models.CharField(_(u'number'), |
289
|
|
|
max_length=50) |
290
|
|
|
location = models.CharField(_(u'location'), |
291
|
|
|
max_length=6, |
292
|
|
|
choices=PHONE_LOCATION_CHOICES, |
293
|
|
|
default='work') |
294
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
295
|
|
|
auto_now_add=True) |
296
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
297
|
|
|
auto_now=True) |
298
|
|
|
|
299
|
|
|
def __unicode__(self): |
300
|
|
|
return u"%s (%s)" % (self.phone_number, self.location) |
301
|
|
|
|
302
|
|
|
class Meta: |
303
|
|
|
db_table = 'contacts_phone_numbers' |
304
|
|
|
app_label = 'pyfreebill' |
305
|
|
|
verbose_name = _(u'phone number') |
306
|
|
|
verbose_name_plural = _(u'phone numbers') |
307
|
|
|
|
308
|
|
|
EMAIL_LOCATION_CHOICES = ( |
309
|
|
|
('work', _(u'Work')), |
310
|
|
|
('home', _(u'Home')), |
311
|
|
|
('billing', _(u'Billing')), |
312
|
|
|
('cdr_month', _(u'CDR (Monthly)')), |
313
|
|
|
('cdr_week', _(u'CDR (Weekly)')), |
314
|
|
|
('cdr_day', _(u'CDR (Daily)')), |
315
|
|
|
('other', _(u'Other')) |
316
|
|
|
) |
317
|
|
|
|
318
|
|
|
|
319
|
|
|
class EmailAddress(models.Model): |
320
|
|
|
content_type = models.ForeignKey( |
321
|
|
|
ContentType, |
322
|
|
|
limit_choices_to={'app_label': 'contacts'}) |
323
|
|
View Code Duplication |
object_id = models.IntegerField(db_index=True) |
|
|
|
|
324
|
|
|
content_object = GenericForeignKey('content_type', 'object_id') |
325
|
|
|
email_address = models.EmailField(_(u'email address')) |
326
|
|
|
location = models.CharField(_(u'location'), |
327
|
|
|
max_length=10, |
328
|
|
|
choices=EMAIL_LOCATION_CHOICES, |
329
|
|
|
default='work') |
330
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
331
|
|
|
auto_now_add=True) |
332
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
333
|
|
|
auto_now=True) |
334
|
|
|
|
335
|
|
|
def __unicode__(self): |
336
|
|
|
return u"%s (%s)" % (self.email_address, self.location) |
337
|
|
|
|
338
|
|
|
class Meta: |
339
|
|
|
db_table = 'contacts_email_addresses' |
340
|
|
|
app_label = 'pyfreebill' |
341
|
|
|
verbose_name = _(u'email address') |
342
|
|
|
verbose_name_plural = _(u'email addresses') |
343
|
|
|
|
344
|
|
|
|
345
|
|
|
LOCATION_CHOICES = ( |
346
|
|
|
('work', _(u'Work')), |
347
|
|
|
('home', _(u'Home')), |
348
|
|
|
('mobile', _(u'Mobile')), |
349
|
|
|
('fax', _(u'Fax')), |
350
|
|
|
('person', _(u'Personal')), |
351
|
|
|
('other', _(u'Other')) |
352
|
|
|
) |
353
|
|
|
|
354
|
|
|
|
355
|
|
|
class WebSite(models.Model): |
356
|
|
|
content_type = models.ForeignKey( |
357
|
|
|
ContentType, |
358
|
|
|
limit_choices_to={'app_label': 'contacts'}) |
359
|
|
View Code Duplication |
object_id = models.IntegerField(db_index=True) |
|
|
|
|
360
|
|
|
content_object = GenericForeignKey('content_type', 'object_id') |
361
|
|
|
url = models.URLField(_(u'URL')) |
362
|
|
|
location = models.CharField(_(u'location'), |
363
|
|
|
max_length=6, |
364
|
|
|
choices=LOCATION_CHOICES, |
365
|
|
|
default='work') |
366
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
367
|
|
|
auto_now_add=True) |
368
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
369
|
|
|
auto_now=True) |
370
|
|
|
|
371
|
|
|
def __unicode__(self): |
372
|
|
|
return u"%s (%s)" % (self.url, self.location) |
373
|
|
|
|
374
|
|
|
class Meta: |
375
|
|
|
db_table = 'contacts_web_sites' |
376
|
|
|
app_label = 'pyfreebill' |
377
|
|
|
verbose_name = _(u'web site') |
378
|
|
|
verbose_name_plural = _(u'web sites') |
379
|
|
|
|
380
|
|
|
def get_absolute_url(self): |
381
|
|
|
return u"%s?web_site=%s" % (self.content_object.get_absolute_url(), self.pk) |
382
|
|
|
|
383
|
|
|
|
384
|
|
|
class StreetAddress(models.Model): |
385
|
|
|
content_type = models.ForeignKey( |
386
|
|
|
ContentType, |
387
|
|
|
limit_choices_to={'app_label': 'contacts'}) |
388
|
|
|
object_id = models.IntegerField(db_index=True) |
389
|
|
|
content_object = GenericForeignKey('content_type', 'object_id') |
390
|
|
|
street = models.TextField(_(u'street'), |
391
|
|
|
blank=True) |
392
|
|
|
city = models.CharField(_(u'city'), |
393
|
|
|
max_length=200, |
394
|
|
|
blank=True) |
395
|
|
|
province = models.CharField(_(u'province'), |
396
|
|
|
max_length=200, |
397
|
|
|
blank=True) |
398
|
|
|
postal_code = models.CharField(_(u'postal code'), |
399
|
|
|
max_length=10, |
400
|
|
|
blank=True) |
401
|
|
|
country = CountryField(_(u'country')) |
402
|
|
|
location = models.CharField(_(u'location'), |
403
|
|
|
max_length=6, |
404
|
|
|
choices=LOCATION_CHOICES, |
405
|
|
|
default='work') |
406
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
407
|
|
|
auto_now_add=True) |
408
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
409
|
|
|
auto_now=True) |
410
|
|
|
|
411
|
|
|
def __unicode__(self): |
412
|
|
|
return u"%s (%s)" % (self.city, self.location) |
413
|
|
|
|
414
|
|
|
class Meta: |
415
|
|
|
db_table = 'contacts_street_addresses' |
416
|
|
|
app_label = 'pyfreebill' |
417
|
|
|
verbose_name = _(u'street address') |
418
|
|
|
verbose_name_plural = _(u'street addresses') |
419
|
|
|
|
420
|
|
|
|
421
|
|
|
class CompanyBalanceHistory(models.Model): |
422
|
|
|
""" Company balance history Model """ |
423
|
|
|
company = models.ForeignKey(Company, |
424
|
|
|
verbose_name=_(u"company")) |
425
|
|
|
amount_debited = models.DecimalField(_(u'amount debited'), |
426
|
|
|
max_digits=12, |
427
|
|
|
decimal_places=4) |
428
|
|
|
amount_refund = models.DecimalField(_(u'amount refund'), |
429
|
|
|
max_digits=12, |
430
|
|
|
decimal_places=4) |
431
|
|
|
customer_balance = models.DecimalField(_(u'customer balance'), |
432
|
|
|
max_digits=12, |
433
|
|
|
decimal_places=4, |
434
|
|
|
default=0, |
435
|
|
|
help_text=_(u"""Resulting customer |
436
|
|
|
balance.""")) |
437
|
|
|
supplier_balance = models.DecimalField(_(u'provider balance'), |
438
|
|
|
max_digits=12, |
439
|
|
|
decimal_places=4, |
440
|
|
|
default=0, |
441
|
|
|
help_text=_(u"""Resulting provider |
442
|
|
|
balance.""")) |
443
|
|
|
OPERATION_TYPE_CHOICES = ( |
444
|
|
|
('customer', _(u"operation on customer account")), |
445
|
|
|
('provider', _(u"operation on provider account")), |
446
|
|
|
) |
447
|
|
|
operation_type = models.CharField(_(u"operation type"), |
448
|
|
|
max_length=10, |
449
|
|
|
choices=OPERATION_TYPE_CHOICES, |
450
|
|
|
default='customer') |
451
|
|
|
reference = models.CharField(_(u'public description'), |
452
|
|
|
max_length=255, |
453
|
|
|
blank=True) |
454
|
|
|
description = models.CharField(_(u'internal description'), |
455
|
|
|
max_length=255, |
456
|
|
|
blank=True) |
457
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
458
|
|
|
auto_now_add=True) |
459
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
460
|
|
|
auto_now=True) |
461
|
|
|
|
462
|
|
|
class Meta: |
463
|
|
|
db_table = 'company_balance_history' |
464
|
|
|
app_label = 'pyfreebill' |
465
|
|
|
ordering = ('company', 'date_added') |
466
|
|
|
verbose_name = _(u'Company balance history') |
467
|
|
|
verbose_name_plural = _(u'Company balance history') |
468
|
|
|
|
469
|
|
|
def __unicode__(self): |
470
|
|
|
return u"%s %s %s %s" % (self.company, |
471
|
|
|
self.amount_debited, |
472
|
|
|
self.amount_refund, |
473
|
|
|
self.operation_type) |
474
|
|
|
|
475
|
|
|
|
476
|
|
|
# Caller ID list |
477
|
|
|
|
478
|
|
|
class CalleridPrefixList(models.Model): |
479
|
|
|
""" CallerID List """ |
480
|
|
|
name = models.CharField(_(u'name'), |
481
|
|
|
max_length=128, |
482
|
|
View Code Duplication |
unique=True) |
|
|
|
|
483
|
|
|
description = models.TextField(_(u'description'), |
484
|
|
|
blank=True) |
485
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
486
|
|
|
auto_now_add=True) |
487
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
488
|
|
|
auto_now=True) |
489
|
|
|
|
490
|
|
|
class Meta: |
491
|
|
|
db_table = 'callerid_prefix_list' |
492
|
|
|
app_label = 'pyfreebill' |
493
|
|
|
ordering = ('name',) |
494
|
|
|
verbose_name = _(u'CallerID prefix list') |
495
|
|
|
verbose_name_plural = _(u'CallerID prefix lists') |
496
|
|
|
|
497
|
|
|
def __unicode__(self): |
498
|
|
|
return u"%s" % self.name |
499
|
|
|
|
500
|
|
|
def prefix(self): |
501
|
|
|
html = '<span><a href="/extranet/pyfreebill/calleridprefix/?calleridprefixlist__id__exact={0}" class="btn btn-inverse btn-mini">Prefix <i class="icon-plus-sign"></i></a></span>' |
502
|
|
|
return format_html(html, (self.id)) |
503
|
|
|
prefix.allow_tags = True |
504
|
|
|
prefix.short_description = _(u'prefix') |
505
|
|
|
|
506
|
|
|
|
507
|
|
|
class CalleridPrefix(models.Model): |
508
|
|
|
""" Customer Rates Model """ |
509
|
|
|
calleridprefixlist = models.ForeignKey( |
510
|
|
|
CalleridPrefixList, |
511
|
|
|
verbose_name=_(u"callerid prefix list")) |
512
|
|
|
prefix = models.CharField(_(u'numeric prefix'), |
513
|
|
|
max_length=30, |
514
|
|
|
db_index=True) |
515
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
516
|
|
|
auto_now_add=True) |
517
|
|
View Code Duplication |
date_modified = models.DateTimeField(_(u'date modified'), |
|
|
|
|
518
|
|
|
auto_now=True) |
519
|
|
|
|
520
|
|
|
class Meta: |
521
|
|
|
db_table = 'caller_id_prefix' |
522
|
|
|
app_label = 'pyfreebill' |
523
|
|
|
ordering = ('calleridprefixlist', 'prefix') |
524
|
|
|
unique_together = ("calleridprefixlist", "prefix") |
525
|
|
|
verbose_name = _(u'Callerid prefix') |
526
|
|
|
verbose_name_plural = _(u'Callerid prefix') |
527
|
|
|
|
528
|
|
|
def __unicode__(self): |
529
|
|
|
return u"%s" % self.prefix |
530
|
|
|
|
531
|
|
|
# Provider Rates |
532
|
|
|
|
533
|
|
|
|
534
|
|
|
class ProviderTariff(models.Model): |
535
|
|
|
""" Provider tariff """ |
536
|
|
|
name = models.CharField(_(u"name"), |
537
|
|
|
max_length=128) |
538
|
|
|
carrier = models.ForeignKey(Company, |
539
|
|
|
verbose_name=_(u"Provider"), |
540
|
|
|
limit_choices_to={'supplier_enabled': True}) |
541
|
|
|
lead_strip = models.CharField(_(u'lead strip'), |
542
|
|
|
blank=True, |
543
|
|
|
default='', |
544
|
|
|
max_length=15) |
545
|
|
|
tail_strip = models.CharField(_(u'tail strip'), |
546
|
|
|
blank=True, |
547
|
|
|
default='', |
548
|
|
|
max_length=15) |
549
|
|
|
prefix = models.CharField(_(u'prefix'), |
550
|
|
|
blank=True, |
551
|
|
|
default='', |
552
|
|
|
max_length=15) |
553
|
|
|
suffix = models.CharField(_(u'suffix'), |
554
|
|
|
blank=True, |
555
|
|
|
default='', |
556
|
|
|
max_length=15) |
557
|
|
|
description = models.TextField(_(u'description'), |
558
|
|
|
blank=True) |
559
|
|
|
CALLERID_FILTER_CHOICES = ( |
560
|
|
|
('1', _(u"No filter")), |
561
|
|
|
('2', _(u"Prefix authorized")), |
562
|
|
|
('3', _(u"Prefix prohibited")), |
563
|
|
|
) |
564
|
|
|
callerid_filter = models.CharField(_(u"CallerID Prefix filter"), |
565
|
|
|
max_length=2, |
566
|
|
|
choices=CALLERID_FILTER_CHOICES, |
567
|
|
|
default='1') |
568
|
|
|
callerid_list = models.ForeignKey(CalleridPrefixList, |
569
|
|
|
verbose_name=_(u"CallerID prefix List"), |
570
|
|
|
blank=True, |
571
|
|
|
null=True) |
572
|
|
|
date_start = models.DateTimeField() |
573
|
|
|
date_end = models.DateTimeField() |
574
|
|
|
quality = models.IntegerField(_(u'quality'), |
575
|
|
|
blank=True, |
576
|
|
|
default='100', |
577
|
|
|
help_text=_(u"Order by quality.")) |
578
|
|
|
reliability = models.IntegerField(_(u'reliability'), |
579
|
|
|
blank=True, |
580
|
|
|
default='100', |
581
|
|
|
help_text=_(u"Order by reliability.")) |
582
|
|
|
cid = models.CharField(_(u'cid'), |
583
|
|
|
blank=True, |
584
|
|
|
default='', |
585
|
|
|
max_length=25, |
586
|
|
|
help_text=_(u"Regex to modify CallerID number.")) |
587
|
|
|
enabled = models.BooleanField(_(u"Enabled / Disabled"), |
588
|
|
|
default=True) |
589
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
590
|
|
|
auto_now_add=True) |
591
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
592
|
|
|
auto_now=True) |
593
|
|
|
|
594
|
|
|
class Meta: |
595
|
|
|
db_table = 'provider_tariff' |
596
|
|
|
app_label = 'pyfreebill' |
597
|
|
|
ordering = ('enabled', |
598
|
|
|
'quality', |
599
|
|
|
'reliability') |
600
|
|
|
verbose_name = _(u'provider ratecard') |
601
|
|
|
verbose_name_plural = _(u'provider ratecards') |
602
|
|
|
|
603
|
|
|
def __unicode__(self): |
604
|
|
|
return u"%s" % self.name |
605
|
|
|
|
606
|
|
|
def rates(self): |
607
|
|
|
html = '<span><a href="/extranet/pyfreebill/providerrates/?provider_tariff__id__exact={0}" class="btn btn-inverse btn-mini">Rates <i class="icon-plus-sign"></i></a></span>' |
608
|
|
|
return format_html(html, (self.id)) |
609
|
|
|
rates.allow_tags = True |
610
|
|
|
rates.short_description = _(u'rates') |
611
|
|
|
|
612
|
|
|
|
613
|
|
|
class ProviderRates(models.Model): |
614
|
|
|
""" Provider Rates Model """ |
615
|
|
|
destination = models.CharField(_(u'destination'), |
616
|
|
|
blank=True, |
617
|
|
|
default='', |
618
|
|
|
null=True, |
619
|
|
|
max_length=128, |
620
|
|
|
db_index=True) |
621
|
|
|
digits = models.CharField(_(u'numeric prefix'), |
622
|
|
|
max_length=30, |
623
|
|
|
db_index=True) |
624
|
|
|
cost_rate = models.DecimalField(_(u'Cost rate'), |
625
|
|
|
max_digits=11, |
626
|
|
|
decimal_places=5) |
627
|
|
|
block_min_duration = models.IntegerField(_(u'block min duration'), |
628
|
|
|
default=1) |
629
|
|
|
init_block = models.DecimalField(_(u'Init block rate'), |
630
|
|
|
max_digits=11, |
631
|
|
|
decimal_places=5, |
632
|
|
|
default=0) |
633
|
|
|
provider_tariff = models.ForeignKey(ProviderTariff) |
634
|
|
|
# date_start = models.DateTimeField() |
635
|
|
|
# date_end = models.DateTimeField() |
636
|
|
|
enabled = models.BooleanField(_(u"Enabled / Disabled"), default=True) |
637
|
|
|
date_added = models.DateTimeField(_(u'date added'), auto_now_add=True) |
638
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), auto_now=True) |
639
|
|
|
|
640
|
|
|
class Meta: |
641
|
|
|
db_table = 'provider_rates' |
642
|
|
|
app_label = 'pyfreebill' |
643
|
|
|
ordering = ('enabled', 'provider_tariff', 'digits') |
644
|
|
|
index_together = [ |
645
|
|
|
["provider_tariff", "digits", "enabled"], |
646
|
|
|
] |
647
|
|
|
unique_together = ("digits", "provider_tariff") |
648
|
|
|
verbose_name = _(u'provider rate') |
649
|
|
|
verbose_name_plural = _(u'provider rates') |
650
|
|
|
|
651
|
|
|
def __unicode__(self): |
652
|
|
|
return u"%s %s %s " % (self.digits, |
653
|
|
|
self.cost_rate, |
654
|
|
|
self.provider_tariff) |
655
|
|
|
|
656
|
|
|
def set_bar(self, value): |
657
|
|
|
self.bar = value |
658
|
|
|
simple_import_methods = ('set_bar',) |
659
|
|
|
|
660
|
|
|
|
661
|
|
|
# LCR |
662
|
|
|
|
663
|
|
|
|
664
|
|
|
class LCRGroup(models.Model): |
665
|
|
|
""" LCR group model """ |
666
|
|
|
name = models.CharField(_(u"name"), |
667
|
|
|
max_length=128, |
668
|
|
|
unique=True) |
669
|
|
|
description = models.TextField(_(u'description'), |
670
|
|
|
blank=True) |
671
|
|
|
LCR_TYPE_CHOICES = ( |
672
|
|
|
('p', _(u"lower price")), |
673
|
|
|
('q', _(u"best quality")), |
674
|
|
|
('r', _(u"best reliability")), |
675
|
|
|
('l', _(u"load balance")), |
676
|
|
|
) |
677
|
|
|
lcrtype = models.CharField(_(u"lcr type"), |
678
|
|
|
max_length=10, |
679
|
|
|
choices=LCR_TYPE_CHOICES, |
680
|
|
|
default='p') |
681
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
682
|
|
|
auto_now_add=True) |
683
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
684
|
|
|
auto_now=True) |
685
|
|
|
|
686
|
|
|
class Meta: |
687
|
|
|
db_table = 'lcr_group' |
688
|
|
|
app_label = 'pyfreebill' |
689
|
|
|
ordering = ('name',) |
690
|
|
|
verbose_name = _(u'LCR') |
691
|
|
|
verbose_name_plural = _(u'LCRs') |
692
|
|
|
|
693
|
|
|
def __unicode__(self): |
694
|
|
|
return u"%s %s " % (self.name, self.lcrtype) |
695
|
|
|
|
696
|
|
|
|
697
|
|
|
class LCRProviders(models.Model): |
698
|
|
|
""" LCR group model """ |
699
|
|
|
lcr = models.ForeignKey(LCRGroup, |
700
|
|
|
verbose_name=_(u"LCR")) |
701
|
|
|
provider_tariff = models.ForeignKey(ProviderTariff, |
702
|
|
|
verbose_name=_(u"Provider tariff")) |
703
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
704
|
|
View Code Duplication |
auto_now_add=True) |
|
|
|
|
705
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
706
|
|
|
auto_now=True) |
707
|
|
|
|
708
|
|
|
class Meta: |
709
|
|
|
db_table = 'lcr_providers' |
710
|
|
|
app_label = 'pyfreebill' |
711
|
|
|
verbose_name = _(u'LCR provider') |
712
|
|
|
verbose_name_plural = _(u'LCR providers') |
713
|
|
|
|
714
|
|
|
def __unicode__(self): |
715
|
|
|
return u"%s - %s " % (self.lcr, self.provider_tariff) |
716
|
|
|
|
717
|
|
|
def rates(self): |
718
|
|
|
html = '<span><a href="/extranet/pyfreebill/providerrates/?provider_tariff__id__exact={0}" class="btn btn-inverse btn-mini">Rates <i class="icon-plus-sign"></i></a></span>' |
719
|
|
|
return format_html(html, (self.provider_tariff)) |
720
|
|
|
rates.allow_tags = True |
721
|
|
|
rates.short_description = _(u'rates') |
722
|
|
|
|
723
|
|
|
|
724
|
|
|
# Ratecard |
725
|
|
|
def default_time(): |
726
|
|
|
return timezone.now() + timezone.timedelta(days=3650) |
727
|
|
|
|
728
|
|
|
class RateCard(models.Model): |
729
|
|
|
""" RateCard Model """ |
730
|
|
|
name = models.CharField(_(u'name'), |
731
|
|
|
max_length=128, |
732
|
|
|
unique=True) |
733
|
|
|
RCTYPE_CHOICES = ( |
734
|
|
|
("PSTN", _(u"CALLS TO PSTN")), |
735
|
|
|
("DIDIN", _(u"DID - INBOUND CALLS")), |
736
|
|
|
("DIDOUT", _(u"OUTBOUND CALLS TO INTERNAL DID")), |
737
|
|
|
("EMERGENCY", _(u"EMERGENCY CALLS")) |
738
|
|
|
) |
739
|
|
|
rctype = models.CharField( |
740
|
|
|
_(u"Type of ratecards"), |
741
|
|
|
max_length=10, |
742
|
|
|
default="PSTN", |
743
|
|
|
choices=RCTYPE_CHOICES, |
744
|
|
|
help_text=_(u"""Select the right ratecard |
745
|
|
|
regarding the type of calls. Default is PSTN""")) |
746
|
|
|
description = models.TextField(_(u'description'), |
747
|
|
|
blank=True) |
748
|
|
|
lcrgroup = models.ForeignKey(LCRGroup, |
749
|
|
|
verbose_name=_(u"lcr")) |
750
|
|
|
CALLERID_FILTER_CHOICES = ( |
751
|
|
|
('1', _(u"No filter")), |
752
|
|
|
('2', _(u"Prefix authorized")), |
753
|
|
|
('3', _(u"Prefix prohibited")), |
754
|
|
|
) |
755
|
|
|
callerid_filter = models.CharField(_(u"CallerID Prefix filter"), |
756
|
|
|
max_length=2, |
757
|
|
|
choices=CALLERID_FILTER_CHOICES, |
758
|
|
|
default='1') |
759
|
|
|
callerid_list = models.ForeignKey(CalleridPrefixList, |
760
|
|
|
verbose_name=_(u"CallerID prefix List"), |
761
|
|
|
blank=True, |
762
|
|
|
null=True) |
763
|
|
|
enabled = models.BooleanField(_(u"Enabled / Disabled"), |
764
|
|
|
default=True) |
765
|
|
|
date_start = models.DateTimeField(default=timezone.now) |
766
|
|
|
date_end = models.DateTimeField(default=default_time) |
767
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
768
|
|
|
auto_now_add=True) |
769
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
770
|
|
|
auto_now=True) |
771
|
|
|
|
772
|
|
|
class Meta: |
773
|
|
|
db_table = 'ratecard' |
774
|
|
|
app_label = 'pyfreebill' |
775
|
|
|
ordering = ('name', 'enabled') |
776
|
|
|
verbose_name = _(u'Customer ratecard') |
777
|
|
|
verbose_name_plural = _(u'Customer ratecards') |
778
|
|
|
|
779
|
|
|
def __unicode__(self): |
780
|
|
|
return u"%s (%s) %s" % (self.name, self.rctype, self.enabled) |
781
|
|
|
|
782
|
|
|
def rates(self): |
783
|
|
|
html = '<span><a href="/extranet/pyfreebill/customerrates/?ratecard__id__exact={0}" class="btn btn-inverse btn-mini">Rates <i class="icon-plus-sign"></i></a></span>' |
784
|
|
|
return format_html(html, (self.id)) |
785
|
|
|
rates.allow_tags = True |
786
|
|
|
rates.short_description = _(u'Rates') |
787
|
|
|
|
788
|
|
|
def lcr(self): |
789
|
|
|
html = '<span><a href="/extranet/pyfreebill/lcrgroup/{0}/" class="btn btn-inverse btn-mini">LCR <i class="icon-plus-sign"></i></a></span>' |
790
|
|
|
return format_html(html, (self.lcrgroup.pk)) |
791
|
|
|
lcr.allow_tags = True |
792
|
|
|
lcr.short_description = _(u'lcr') |
793
|
|
|
|
794
|
|
|
|
795
|
|
|
class CustomerRates(models.Model): |
796
|
|
|
""" Customer Rates Model """ |
797
|
|
|
ratecard = models.ForeignKey(RateCard, |
798
|
|
|
verbose_name=_(u"ratecard")) |
799
|
|
|
destination = models.CharField(_(u'destination'), |
800
|
|
|
blank=True, |
801
|
|
|
default='', |
802
|
|
|
null=True, |
803
|
|
|
max_length=128, |
804
|
|
|
db_index=True) |
805
|
|
|
prefix = models.CharField(_(u'numeric prefix'), |
806
|
|
|
max_length=30, |
807
|
|
|
db_index=True) |
808
|
|
|
destnum_length = models.IntegerField( |
809
|
|
|
_(u'Destination number length'), |
810
|
|
|
default=0, |
811
|
|
|
help_text=_(u"If value > 0, then destination number must match tsi length") |
812
|
|
|
) |
813
|
|
|
rate = models.DecimalField(_(u'sell rate'), |
814
|
|
|
max_digits=11, |
815
|
|
|
decimal_places=5, |
816
|
|
|
help_text=_(u"to block the prefix, put -1")) |
817
|
|
|
block_min_duration = models.IntegerField(_(u'Increment'), |
818
|
|
|
default=1) |
819
|
|
|
minimal_time = models.IntegerField( |
820
|
|
|
_(u'Minimal time'), |
821
|
|
|
default=0, |
822
|
|
|
help_text=_(u"minimal time to be billed in seconds")) |
823
|
|
|
init_block = models.DecimalField(_(u'Connection fee'), |
824
|
|
|
max_digits=11, |
825
|
|
|
decimal_places=5, |
826
|
|
|
default=0) |
827
|
|
|
# date_start = models.DateTimeField() |
828
|
|
|
# date_end = models.DateTimeField() |
829
|
|
|
enabled = models.BooleanField(_(u"Enabled"), |
830
|
|
|
default=True) |
831
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
832
|
|
|
auto_now_add=True) |
833
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
834
|
|
|
auto_now=True) |
835
|
|
|
|
836
|
|
|
class Meta: |
837
|
|
|
db_table = 'customer_rates' |
838
|
|
|
app_label = 'pyfreebill' |
839
|
|
|
ordering = ('ratecard', 'prefix', 'enabled') |
840
|
|
|
unique_together = ("ratecard", "prefix") |
841
|
|
|
verbose_name = _(u'customer rate') |
842
|
|
|
verbose_name_plural = _(u'customer rates') |
843
|
|
|
|
844
|
|
|
def __unicode__(self): |
845
|
|
|
return u"%s" % self.ratecard |
846
|
|
|
|
847
|
|
|
|
848
|
|
|
class CustomerRateCards(models.Model): |
849
|
|
|
""" Customer rates Cards Model """ |
850
|
|
|
company = models.ForeignKey(Company, |
851
|
|
|
verbose_name=_(u"company")) |
852
|
|
|
ratecard = models.ForeignKey(RateCard, |
853
|
|
|
verbose_name=_(u"ratecard")) |
854
|
|
|
description = models.CharField( |
855
|
|
|
_(u'Comment'), |
856
|
|
|
max_length=30, |
857
|
|
|
blank=True) |
858
|
|
|
tech_prefix = models.CharField(_(u"technical prefix"), |
859
|
|
|
blank=True, |
860
|
|
|
default='', |
861
|
|
|
null=True, |
862
|
|
|
max_length=7) |
863
|
|
|
DEFAULT_PRIORITY_CHOICES = ( |
864
|
|
|
(1, _(u'1')), |
865
|
|
|
(2, _(u'2')), |
866
|
|
|
(3, _(u'3')), |
867
|
|
|
(4, _(u'4')), |
868
|
|
|
(5, _(u'5')), |
869
|
|
|
(6, _(u'6')), |
870
|
|
|
(7, _(u'7')), |
871
|
|
|
) |
872
|
|
|
priority = models.IntegerField(_(u'priority'), |
873
|
|
|
choices=DEFAULT_PRIORITY_CHOICES, |
874
|
|
|
help_text=_(u"""Priority order, 1 is the |
875
|
|
|
higher priority and 3 the |
876
|
|
|
lower one. Correct values |
877
|
|
|
are : 1 to 7 !.""")) |
878
|
|
|
discount = models.DecimalField(_(u'discount'), |
879
|
|
|
max_digits=3, |
880
|
|
|
decimal_places=2, |
881
|
|
|
default=0, |
882
|
|
|
help_text=_(u"""ratecard discount. For |
883
|
|
|
10% discount, enter 10 !""")) |
884
|
|
|
allow_negative_margin = models.BooleanField(_(u"""Allow calls with |
885
|
|
|
negative margin"""), |
886
|
|
|
default=False) |
887
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
888
|
|
|
auto_now_add=True) |
889
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
890
|
|
|
auto_now=True) |
891
|
|
|
|
892
|
|
|
class Meta: |
893
|
|
|
db_table = 'customer_ratecards' |
894
|
|
|
app_label = 'pyfreebill' |
895
|
|
|
ordering = ('company', 'priority', 'ratecard') |
896
|
|
|
verbose_name = _(u'Customer Ratecard Allocation') |
897
|
|
|
verbose_name_plural = _(u'Customer ratecard Allocations') |
898
|
|
|
|
899
|
|
|
def __unicode__(self): |
900
|
|
|
return u"%s - Priority: %s Desc: %s" % (self.ratecard, |
901
|
|
|
self.priority, |
902
|
|
|
self.description) |
903
|
|
|
|
904
|
|
|
|
905
|
|
|
# NORMALIZATION |
906
|
|
|
|
907
|
|
|
|
908
|
|
|
class DestinationNumberRules(models.Model): |
909
|
|
|
""" Destination Number Normalization Rules """ |
910
|
|
|
prefix = models.CharField(_(u'numeric prefix'), |
911
|
|
|
max_length=30) |
912
|
|
|
description = models.TextField(_(u'description'), |
913
|
|
|
blank=True) |
914
|
|
|
format_num = models.CharField(_(u"Rule format"), |
915
|
|
|
max_length=150, |
916
|
|
|
help_text=_(u"""example for Tunisia : |
917
|
|
|
^216[%d][%d][%d][%d][%d][%d][%d][%d] |
918
|
|
|
$""")) |
919
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
920
|
|
|
auto_now_add=True) |
921
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
922
|
|
|
auto_now=True) |
923
|
|
|
|
924
|
|
View Code Duplication |
class Meta: |
|
|
|
|
925
|
|
|
db_table = 'destination_norm_rules' |
926
|
|
|
app_label = 'pyfreebill' |
927
|
|
|
ordering = ('prefix',) |
928
|
|
|
verbose_name = _(u'Destination Number Normalization Rule') |
929
|
|
|
verbose_name_plural = _(u'Destination Number Normalization Rules') |
930
|
|
|
|
931
|
|
|
def __unicode__(self): |
932
|
|
|
return u"%s -> %s " % (self.prefix, self.format_num) |
933
|
|
|
|
934
|
|
|
|
935
|
|
|
class CustomerNormalizationRules(models.Model): |
936
|
|
|
""" Customer Normalization Rules """ |
937
|
|
|
company = models.ForeignKey(Company, |
938
|
|
|
verbose_name=_(u"customer")) |
939
|
|
|
prefix = models.CharField(_(u'rule title'), |
940
|
|
|
max_length=30) |
941
|
|
|
description = models.TextField(_(u'description'), |
942
|
|
|
blank=True) |
943
|
|
|
remove_prefix = models.CharField(_(u"remove prefix"), |
944
|
|
|
blank=True, |
945
|
|
|
default='', |
946
|
|
|
max_length=15) |
947
|
|
|
add_prefix = models.CharField(_(u"add prefix"), |
948
|
|
|
blank=True, |
949
|
|
|
default='', |
950
|
|
|
max_length=15) |
951
|
|
View Code Duplication |
date_added = models.DateTimeField(_(u'date added'), |
|
|
|
|
952
|
|
|
auto_now_add=True) |
953
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
954
|
|
|
auto_now=True) |
955
|
|
|
|
956
|
|
|
class Meta: |
957
|
|
|
db_table = 'customer_norm_rules' |
958
|
|
|
app_label = 'pyfreebill' |
959
|
|
|
ordering = ('company', 'prefix') |
960
|
|
|
verbose_name = _(u'Customer Normalization Rule') |
961
|
|
|
verbose_name_plural = _(u'Customer Normalization Rules') |
962
|
|
|
|
963
|
|
|
def __unicode__(self): |
964
|
|
|
return u"%s -> %s -%s +%s" % (self.company, |
965
|
|
|
self.prefix, |
966
|
|
|
self.remove_prefix, |
967
|
|
|
self.add_prefix) |
968
|
|
|
|
969
|
|
|
|
970
|
|
|
class CarrierNormalizationRules(models.Model): |
971
|
|
|
""" Carrier Normalization Rules """ |
972
|
|
|
company = models.ForeignKey(Company, |
973
|
|
|
verbose_name=_(u"provider")) |
974
|
|
|
prefix = models.CharField(_(u'prefix'), |
975
|
|
|
max_length=30) |
976
|
|
|
description = models.TextField(_(u'description'), |
977
|
|
|
blank=True) |
978
|
|
|
remove_prefix = models.CharField(_(u"remove prefix"), |
979
|
|
|
blank=True, |
980
|
|
|
default='', |
981
|
|
|
max_length=15) |
982
|
|
|
add_prefix = models.CharField(_(u"add prefix"), |
983
|
|
|
blank=True, |
984
|
|
|
default='', |
985
|
|
|
max_length=15) |
986
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
987
|
|
|
auto_now_add=True) |
988
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
989
|
|
|
auto_now=True) |
990
|
|
|
|
991
|
|
|
class Meta: |
992
|
|
|
db_table = 'carrier_norm_rules' |
993
|
|
|
app_label = 'pyfreebill' |
994
|
|
|
ordering = ('company', 'prefix') |
995
|
|
|
verbose_name = _(u'Provider Normalization Rule') |
996
|
|
|
verbose_name_plural = _(u'Provider Normalization Rules') |
997
|
|
|
|
998
|
|
|
def __unicode__(self): |
999
|
|
|
return u"%s -> %s -%s +%s" % (self.company, |
1000
|
|
|
self.prefix, |
1001
|
|
|
self.remove_prefix, |
1002
|
|
|
self.add_prefix) |
1003
|
|
|
|
1004
|
|
|
|
1005
|
|
|
class CustomerCIDNormalizationRules(models.Model): |
1006
|
|
|
""" Customer Caller ID Number Normalization Rules """ |
1007
|
|
|
company = models.ForeignKey(Company, |
1008
|
|
|
verbose_name=_(u"customer")) |
1009
|
|
|
prefix = models.CharField(_(u'prefix'), |
1010
|
|
|
max_length=30) |
1011
|
|
|
description = models.TextField(_(u'description'), |
1012
|
|
|
blank=True) |
1013
|
|
|
remove_prefix = models.CharField(_(u"remove prefix"), |
1014
|
|
|
blank=True, |
1015
|
|
|
default='', |
1016
|
|
|
max_length=15) |
1017
|
|
|
add_prefix = models.CharField(_(u"add prefix"), |
1018
|
|
|
blank=True, |
1019
|
|
|
default='', |
1020
|
|
|
max_length=15) |
1021
|
|
View Code Duplication |
date_added = models.DateTimeField(_(u'date added'), |
|
|
|
|
1022
|
|
|
auto_now_add=True) |
1023
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
1024
|
|
|
auto_now=True) |
1025
|
|
|
|
1026
|
|
|
class Meta: |
1027
|
|
|
db_table = 'customer_cid_norm_rules' |
1028
|
|
|
app_label = 'pyfreebill' |
1029
|
|
|
ordering = ('company', ) |
1030
|
|
|
verbose_name = _(u'Customer CallerID Normalization Rule') |
1031
|
|
|
verbose_name_plural = _(u'Customer CallerID Normalization Rules') |
1032
|
|
|
|
1033
|
|
|
def __unicode__(self): |
1034
|
|
|
return u"%s -> -%s +%s" % (self.company, |
1035
|
|
|
self.remove_prefix, |
1036
|
|
|
self.add_prefix) |
1037
|
|
|
|
1038
|
|
|
|
1039
|
|
|
class CarrierCIDNormalizationRules(models.Model): |
1040
|
|
|
""" Carrier Caller ID Number Normalization Rules """ |
1041
|
|
|
company = models.ForeignKey(Company, |
1042
|
|
|
verbose_name=_(u"provider")) |
1043
|
|
|
prefix = models.CharField(_(u'prefix'), |
1044
|
|
|
max_length=30) |
1045
|
|
|
description = models.TextField(_(u'description'), |
1046
|
|
|
blank=True) |
1047
|
|
|
remove_prefix = models.CharField(_(u"remove prefix"), |
1048
|
|
|
blank=True, |
1049
|
|
|
default='', |
1050
|
|
|
max_length=15) |
1051
|
|
|
add_prefix = models.CharField(_(u"add prefix"), |
1052
|
|
|
blank=True, |
1053
|
|
|
default='', |
1054
|
|
|
max_length=15) |
1055
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
1056
|
|
|
auto_now_add=True) |
1057
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
1058
|
|
|
auto_now=True) |
1059
|
|
|
|
1060
|
|
|
class Meta: |
1061
|
|
|
db_table = 'carrier_cid_norm_rules' |
1062
|
|
|
app_label = 'pyfreebill' |
1063
|
|
|
ordering = ('company', ) |
1064
|
|
|
verbose_name = _(u'Provider CallerID Normalization Rule') |
1065
|
|
|
verbose_name_plural = _(u'Provider CallerID Normalization Rules') |
1066
|
|
|
|
1067
|
|
|
def __unicode__(self): |
1068
|
|
|
return u"%s -> -%s +%s" % (self.company, |
1069
|
|
|
self.remove_prefix, |
1070
|
|
|
self.add_prefix) |
1071
|
|
|
|
1072
|
|
|
# ACL |
1073
|
|
|
|
1074
|
|
|
|
1075
|
|
|
class AclLists(models.Model): |
1076
|
|
|
""" ACL list model """ |
1077
|
|
|
acl_name = models.CharField(_(u'name'), |
1078
|
|
|
max_length=128) |
1079
|
|
|
DEFAULT_POLICY_CHOICES = ( |
1080
|
|
|
('deny', _(u'deny')), |
1081
|
|
|
('allow', _(u'allow')), |
1082
|
|
|
) |
1083
|
|
|
default_policy = models.CharField(_(u'default policy'), |
1084
|
|
|
max_length=10, |
1085
|
|
|
choices=DEFAULT_POLICY_CHOICES, |
1086
|
|
|
default='deny') |
1087
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
1088
|
|
|
auto_now_add=True) |
1089
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
1090
|
|
|
auto_now=True) |
1091
|
|
View Code Duplication |
|
|
|
|
|
1092
|
|
|
class Meta: |
1093
|
|
|
db_table = 'acl_lists' |
1094
|
|
|
app_label = 'pyfreebill' |
1095
|
|
|
ordering = ('acl_name',) |
1096
|
|
|
verbose_name = _(u'ACL list') |
1097
|
|
|
verbose_name_plural = _(u'ACL lists') |
1098
|
|
|
|
1099
|
|
|
def __unicode__(self): |
1100
|
|
|
return u"%s" % self.acl_name |
1101
|
|
|
|
1102
|
|
|
|
1103
|
|
|
class AclNodes(models.Model): |
1104
|
|
|
""" ACL NODES model """ |
1105
|
|
|
company = models.ForeignKey(Company, |
1106
|
|
|
verbose_name=_(u"company")) |
1107
|
|
|
cidr = models.CharField(_(u"ip/cidr Address"), |
1108
|
|
|
max_length=100, |
1109
|
|
|
help_text=_(u"Customer IP or cidr address.")) |
1110
|
|
|
POLICY_CHOICES = ( |
1111
|
|
|
('deny', _('deny')), |
1112
|
|
|
('allow', _('allow')), |
1113
|
|
|
) |
1114
|
|
|
policy = models.CharField(_(u"policy"), |
1115
|
|
|
max_length=10, |
1116
|
|
|
choices=POLICY_CHOICES, |
1117
|
|
|
default='allow') |
1118
|
|
|
acllist = models.ForeignKey(AclLists, |
1119
|
|
|
verbose_name=_(u"acl list")) |
1120
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
1121
|
|
|
auto_now_add=True) |
1122
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
1123
|
|
|
auto_now=True) |
1124
|
|
|
|
1125
|
|
|
class Meta: |
1126
|
|
|
db_table = 'acl_nodes' |
1127
|
|
|
app_label = 'pyfreebill' |
1128
|
|
|
ordering = ('company', 'policy', 'cidr') |
1129
|
|
|
verbose_name = _(u'ACL node') |
1130
|
|
|
verbose_name_plural = _(u'ACL nodes') |
1131
|
|
|
|
1132
|
|
|
def __unicode__(self): |
1133
|
|
|
return u"%s %s" % (self.company, self.cidr) |
1134
|
|
|
|
1135
|
|
|
# VOIP SWITCH |
1136
|
|
|
|
1137
|
|
|
|
1138
|
|
|
class VoipSwitch(models.Model): |
1139
|
|
|
""" VoipSwitch Profile """ |
1140
|
|
|
name = models.CharField(_(u"Switch name"), |
1141
|
|
|
max_length=50, |
1142
|
|
|
help_text=_(u"Switch name")) |
1143
|
|
|
ip = models.CharField(_(u"switch IP"), |
1144
|
|
|
max_length=100, |
1145
|
|
|
default="auto", |
1146
|
|
|
help_text=_(u"Switch IP.")) |
1147
|
|
|
esl_listen_ip = models.CharField(_(u"event socket switch IP"), |
1148
|
|
View Code Duplication |
max_length=100, |
|
|
|
|
1149
|
|
|
default="127.0.0.1", |
1150
|
|
|
help_text=_(u"Event socket switch IP.")) |
1151
|
|
|
esl_listen_port = models.PositiveIntegerField(_(u"""event socket switch |
1152
|
|
|
port"""), |
1153
|
|
|
default="8021", |
1154
|
|
|
help_text=_(u"""Event socket |
1155
|
|
|
switch port.""")) |
1156
|
|
|
esl_password = models.CharField(_(u"event socket switch password"), |
1157
|
|
|
max_length=30, |
1158
|
|
|
default="ClueCon", |
1159
|
|
|
help_text=_(u"""Event socket switch |
1160
|
|
|
password.""")) |
1161
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
1162
|
|
|
auto_now_add=True) |
1163
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
1164
|
|
|
auto_now=True) |
1165
|
|
|
|
1166
|
|
|
class Meta: |
1167
|
|
|
db_table = 'voip_switch' |
1168
|
|
|
app_label = 'pyfreebill' |
1169
|
|
|
ordering = ('name', ) |
1170
|
|
|
verbose_name = _(u'VoIP Switch') |
1171
|
|
|
verbose_name_plural = _(u'VoIP Switches') |
1172
|
|
|
|
1173
|
|
|
def __unicode__(self): |
1174
|
|
|
return u"%s (:%s)" % (self.name, self.ip) |
1175
|
|
|
|
1176
|
|
|
# SOFIA |
1177
|
|
|
|
1178
|
|
|
|
1179
|
|
|
class SipProfile(models.Model): |
1180
|
|
|
""" Sofia Sip profile """ |
1181
|
|
|
name = models.CharField(_(u"SIP profile name"), |
1182
|
|
|
max_length=50, |
1183
|
|
|
unique=True, |
1184
|
|
|
help_text=_(u"""E.g.: the name you want ...""")) |
1185
|
|
|
user_agent = models.CharField(_(u"User agent name"), |
1186
|
|
|
max_length=50, |
1187
|
|
|
default="pyfreebilling", |
1188
|
|
|
help_text=_(u"""E.g.: the user agent |
1189
|
|
|
you want ... - take care |
1190
|
|
|
with certain characters |
1191
|
|
|
such as @ could cause others sip |
1192
|
|
|
proxies reject yours messages as |
1193
|
|
|
invalid ! """)) |
1194
|
|
|
ext_rtp_ip = models.CharField(_(u"external RTP IP"), |
1195
|
|
|
max_length=100, |
1196
|
|
|
default="auto", |
1197
|
|
|
help_text=_(u"""External/public IP |
1198
|
|
|
address to bind to for RTP.""")) |
1199
|
|
|
ext_sip_ip = models.CharField(_(u"external SIP IP"), |
1200
|
|
|
max_length=100, |
1201
|
|
|
default="auto", |
1202
|
|
|
help_text=_(u"""External/public IP |
1203
|
|
|
address to bind to for |
1204
|
|
|
SIP.""")) |
1205
|
|
|
rtp_ip = models.CharField(_(u"RTP IP"), |
1206
|
|
|
max_length=100, |
1207
|
|
|
default="auto", |
1208
|
|
|
help_text=_(u"""Internal IP address to bind |
1209
|
|
|
to for RTP.""")) |
1210
|
|
|
sip_ip = models.CharField(_(u"SIP IP"), |
1211
|
|
|
max_length=100, |
1212
|
|
|
default="auto", |
1213
|
|
|
help_text=_(u"""Internal IP address to bind |
1214
|
|
|
to for SIP.""")) |
1215
|
|
|
sip_port = models.PositiveIntegerField(_(u"SIP port"), |
1216
|
|
|
default=5060) |
1217
|
|
|
disable_transcoding = models.BooleanField(_(u"disable transcoding"), |
1218
|
|
|
default=True, |
1219
|
|
|
help_text=_(u"""If true, you |
1220
|
|
|
can not use |
1221
|
|
|
transcoding.""")) |
1222
|
|
|
accept_blind_reg = models.BooleanField(_(u"accept blind registration"), |
1223
|
|
|
default=False, |
1224
|
|
|
help_text=_(u"""If true, anyone can |
1225
|
|
|
register to the server |
1226
|
|
|
and will not be |
1227
|
|
|
challenged for |
1228
|
|
|
username/password |
1229
|
|
|
information.""")) |
1230
|
|
|
disable_register = models.BooleanField(_(u"disable register"), |
1231
|
|
|
default=True, |
1232
|
|
|
help_text=_(u"""disable register |
1233
|
|
|
which may be undesirable |
1234
|
|
|
in a public switch """)) |
1235
|
|
|
apply_inbound_acl = models.BooleanField(_(u"Apply an inbound ACL"), |
1236
|
|
|
default=True, |
1237
|
|
|
help_text=_(u"""If true, FS will |
1238
|
|
|
apply the default acl |
1239
|
|
|
list : domains """)) |
1240
|
|
|
auth_calls = models.BooleanField(_(u"authenticate calls"), |
1241
|
|
|
default=True, |
1242
|
|
|
help_text=_(u"""If true, FreeeSWITCH will |
1243
|
|
|
authorize all calls on this |
1244
|
|
|
profile, i.e. challenge the |
1245
|
|
|
other side for |
1246
|
|
|
username/password information. |
1247
|
|
|
""")) |
1248
|
|
|
log_auth_failures = models.BooleanField(_(u"log auth failures"), |
1249
|
|
|
default=False, |
1250
|
|
|
help_text=_(u"""It true, log |
1251
|
|
|
authentication failures. |
1252
|
|
|
Required for Fail2ban. |
1253
|
|
|
""")) |
1254
|
|
|
MULTIPLE_CODECS_CHOICES = ( |
1255
|
|
|
("PCMA,PCMU,G729", _(u"PCMA,PCMU,G729")), |
1256
|
|
|
("PCMU,PCMA,G729", _(u"PCMU,PCMA,G729")), |
1257
|
|
|
("G729,PCMA,PCMU", _(u"G729,PCMA,PCMU")), |
1258
|
|
|
("G729,PCMU,PCMA", _(u"G729,PCMU,PCMA")), |
1259
|
|
|
("PCMA,G729", _(u"PCMA,G729")), |
1260
|
|
|
("PCMU,G729", _(u"PCMU,G729")), |
1261
|
|
|
("G729,PCMA", _(u"G729,PCMA")), |
1262
|
|
|
("G729,PCMU", _(u"G729,PCMU")), |
1263
|
|
|
("PCMA,PCMU", _(u"PCMA,PCMU")), |
1264
|
|
|
("PCMU,PCMA", _(u"PCMU,PCMA")), |
1265
|
|
|
("G722,PCMA,PCMU", _(u"G722,PCMA,PCMU")), |
1266
|
|
|
("G722,PCMU,PCMA", _(u"G722,PCMU,PCMA")), |
1267
|
|
|
("G722", _(u"G722")), |
1268
|
|
|
("G729", _(u"G729")), |
1269
|
|
|
("PCMU", _(u"PCMU")), |
1270
|
|
|
("PCMA", _(u"PCMA")), |
1271
|
|
|
("ALL", _(u"ALL")), |
1272
|
|
|
) |
1273
|
|
|
inbound_codec_prefs = models.CharField(_(u"inbound codec prefs"), |
1274
|
|
|
max_length=100, |
1275
|
|
|
choices=MULTIPLE_CODECS_CHOICES, |
1276
|
|
|
default="G729,PCMU,PCMA", |
1277
|
|
|
help_text=_(u"""Define allowed |
1278
|
|
|
preferred codecs for |
1279
|
|
|
inbound calls.""")) |
1280
|
|
|
outbound_codec_prefs = models.CharField(_(u"outbound codec prefs"), |
1281
|
|
|
max_length=100, |
1282
|
|
|
choices=MULTIPLE_CODECS_CHOICES, |
1283
|
|
|
default="G729,PCMU,PCMA", |
1284
|
|
|
help_text=_(u"""Define allowed |
1285
|
|
|
preferred codecs for |
1286
|
|
|
outbound calls.""")) |
1287
|
|
|
aggressive_nat_detection = models.BooleanField(_(u"""Agressive NAT |
1288
|
|
|
detection"""), |
1289
|
|
|
default=False, |
1290
|
|
|
help_text=_(u"""This will |
1291
|
|
|
enable NAT mode |
1292
|
|
|
if the network |
1293
|
|
|
IP/port from |
1294
|
|
|
which therequest |
1295
|
|
|
was received |
1296
|
|
|
differs from the |
1297
|
|
|
IP/Port |
1298
|
|
|
combination in |
1299
|
|
|
the SIP Via: |
1300
|
|
|
header, or if |
1301
|
|
|
the Via: header |
1302
|
|
|
contains the |
1303
|
|
|
received |
1304
|
|
|
parameter""")) |
1305
|
|
|
NDLB_rec_in_nat_reg_c = models.BooleanField(_(u"""NDLB received |
1306
|
|
|
in nat reg contact"""), |
1307
|
|
|
default=False, |
1308
|
|
|
help_text=_(u"""add a;received= |
1309
|
|
|
"ip:port" |
1310
|
|
|
to the contact when |
1311
|
|
|
replying to |
1312
|
|
|
register |
1313
|
|
|
for nat handling |
1314
|
|
|
""")) |
1315
|
|
|
NDLB_FP_CHOICES = ( |
1316
|
|
|
("true", _(u"true")), |
1317
|
|
|
("safe", _(u"safe")), |
1318
|
|
|
) |
1319
|
|
|
NDLB_force_rport = models.CharField(_(u"""NDLB Force rport"""), |
1320
|
|
|
max_length=10, |
1321
|
|
|
choices=NDLB_FP_CHOICES, |
1322
|
|
|
null=True, |
1323
|
|
|
blank=True, |
1324
|
|
|
default="Null", |
1325
|
|
|
help_text=_(u"""This will force |
1326
|
|
|
FreeSWITCH to send |
1327
|
|
|
SIP responses to the |
1328
|
|
|
network port from |
1329
|
|
|
which they were received. |
1330
|
|
|
Use at your own risk!""")) |
1331
|
|
|
NDLB_broken_auth_hash = models.BooleanField(_(u"""NDLB broken auth hash |
1332
|
|
|
"""), |
1333
|
|
|
default=False, |
1334
|
|
|
help_text=_(u"""Used for when |
1335
|
|
|
phones respond to a |
1336
|
|
|
challenged ACK |
1337
|
|
|
with method INVITE |
1338
|
|
|
in the hash""")) |
1339
|
|
|
enable_timer = models.BooleanField(_(u"""Enable timer"""), |
1340
|
|
|
default=False, |
1341
|
|
|
help_text=_(u"""This enables or disables |
1342
|
|
|
support for RFC 4028 SIP |
1343
|
|
|
Session Timers""")) |
1344
|
|
|
session_timeout = models.PositiveIntegerField(_(u"""Session timeout"""), |
1345
|
|
|
default=1800, |
1346
|
|
|
help_text=_(u"""session |
1347
|
|
|
timers for all |
1348
|
|
|
call to expire |
1349
|
|
|
after the |
1350
|
|
|
specified seconds |
1351
|
|
|
Then it will send |
1352
|
|
|
another invite |
1353
|
|
|
--re-invite. If |
1354
|
|
|
not specified |
1355
|
|
|
defaults to 30 |
1356
|
|
|
minutes. Some |
1357
|
|
|
gateways may |
1358
|
|
|
reject values |
1359
|
|
|
less than 30 |
1360
|
|
|
minutes. This |
1361
|
|
|
values refers to |
1362
|
|
|
Session-Expires |
1363
|
|
|
in RFC 4028 -The |
1364
|
|
|
time at which |
1365
|
|
|
an element will |
1366
|
|
|
consider the |
1367
|
|
|
session timed |
1368
|
|
|
out, if no |
1369
|
|
|
successful |
1370
|
|
|
session refresh |
1371
|
|
|
transaction |
1372
|
|
|
occurs |
1373
|
|
|
beforehand- |
1374
|
|
|
""")) |
1375
|
|
|
rtp_rewrite_timestamps = models.BooleanField(_(u"""RTP rewrite timestamps"""), |
1376
|
|
|
default=False, |
1377
|
|
|
help_text=_(u"""If you don't want to pass |
1378
|
|
|
through timestampes from 1 RTP call |
1379
|
|
|
to another""")) |
1380
|
|
|
pass_rfc2833 = models.BooleanField(_(u"""pass rfc2833"""), |
1381
|
|
|
default=False, |
1382
|
|
|
help_text=_(u"""pass rfc2833""")) |
1383
|
|
|
enabled = models.BooleanField( |
1384
|
|
|
_(u"Enabled"), |
1385
|
|
|
default=True) |
1386
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
1387
|
|
|
auto_now_add=True) |
1388
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
1389
|
|
|
auto_now=True) |
1390
|
|
|
|
1391
|
|
|
class Meta: |
1392
|
|
|
db_table = 'sip_profile' |
1393
|
|
|
app_label = 'pyfreebill' |
1394
|
|
|
ordering = ('name', ) |
1395
|
|
|
unique_together = ("sip_ip", "sip_port") |
1396
|
|
|
verbose_name = _(u'SIP profile') |
1397
|
|
|
verbose_name_plural = _(u'SIP profiles') |
1398
|
|
|
|
1399
|
|
|
def __unicode__(self): |
1400
|
|
|
return u"%s (%s:%s)" % (self.name, self.sip_ip, self.sip_port) |
1401
|
|
|
|
1402
|
|
|
def get_gateways(self): |
1403
|
|
|
"""Get all gateways in the system assigned to this sip profile.""" |
1404
|
|
|
retval = [] |
1405
|
|
|
accounts = Company.objects.filter(supplier_enabled=True) |
1406
|
|
|
for account in accounts: |
1407
|
|
|
for gateway in account.sofiagateway_set.all(): |
1408
|
|
|
if gateway.sip_profile.id == self.id: |
1409
|
|
|
retval.append(gateway) |
1410
|
|
|
return retval |
1411
|
|
|
|
1412
|
|
|
|
1413
|
|
|
class SofiaGateway(models.Model): |
1414
|
|
|
name = models.CharField(_(u"name"), |
1415
|
|
|
max_length=100, |
1416
|
|
|
unique=True) |
1417
|
|
|
domain = models.ForeignKey( |
1418
|
|
|
Domain, |
1419
|
|
|
verbose_name=_(u"SIP domain"), |
1420
|
|
|
help_text=_(u"""A gateway must belong to a domain. |
1421
|
|
|
This domain must be used in SIP message""")) |
1422
|
|
|
company = models.ForeignKey(Company, |
1423
|
|
|
verbose_name=_(u"Provider"), |
1424
|
|
|
db_index=True) |
1425
|
|
|
channels = models.PositiveIntegerField(_(u"channels number"), |
1426
|
|
|
default=1, |
1427
|
|
|
help_text=_(u"""maximum simultaneous |
1428
|
|
|
calls allowed for this gateway. |
1429
|
|
|
""")) |
1430
|
|
|
enabled = models.BooleanField(_(u"Enabled"), |
1431
|
|
|
default=True) |
1432
|
|
|
prefix = models.CharField(_(u'prefix'), |
1433
|
|
|
blank=True, |
1434
|
|
|
default='', |
1435
|
|
|
max_length=15) |
1436
|
|
|
suffix = models.CharField(_(u'suffix'), |
1437
|
|
|
blank=True, |
1438
|
|
|
default='', |
1439
|
|
|
max_length=15) |
1440
|
|
|
MULTIPLE_CODECS_CHOICES = ( |
1441
|
|
|
("PCMA,PCMU,G729", _(u"PCMA,PCMU,G729")), |
1442
|
|
|
("PCMU,PCMA,G729", _(u"PCMU,PCMA,G729")), |
1443
|
|
|
("G729,PCMA,PCMU", _(u"G729,PCMA,PCMU")), |
1444
|
|
|
("G729,PCMU,PCMA", _(u"G729,PCMU,PCMA")), |
1445
|
|
|
("PCMA,G729", _(u"PCMA,G729")), |
1446
|
|
|
("PCMU,G729", _(u"PCMU,G729")), |
1447
|
|
|
("G729,PCMA", _(u"G729,PCMA")), |
1448
|
|
|
("G729,PCMU", _(u"G729,PCMU")), |
1449
|
|
|
("PCMA,PCMU", _(u"PCMA,PCMU")), |
1450
|
|
|
("PCMU,PCMA", _(u"PCMU,PCMA")), |
1451
|
|
|
("G722,PCMA,PCMU", _(u"G722,PCMA,PCMU")), |
1452
|
|
|
("G722,PCMU,PCMA", _(u"G722,PCMU,PCMA")), |
1453
|
|
|
("G722", _(u"G722")), |
1454
|
|
|
("G729", _(u"G729")), |
1455
|
|
|
("PCMU", _(u"PCMU")), |
1456
|
|
|
("PCMA", _(u"PCMA")), |
1457
|
|
|
("ALL", _(u"ALL")), |
1458
|
|
|
) |
1459
|
|
|
codec = models.CharField(_(u"Codecs"), |
1460
|
|
|
max_length=30, |
1461
|
|
|
default="ALL", |
1462
|
|
|
choices=MULTIPLE_CODECS_CHOICES, |
1463
|
|
|
help_text=_(u"""Codecs allowed - beware about |
1464
|
|
|
order, 1st has high priority """)) |
1465
|
|
|
username = models.CharField(_(u"username"), |
1466
|
|
|
blank=True, |
1467
|
|
|
default='', |
1468
|
|
|
max_length=35) |
1469
|
|
|
password = models.CharField(_(u"password"), |
1470
|
|
|
blank=True, |
1471
|
|
|
default='', |
1472
|
|
|
max_length=35) |
1473
|
|
|
register = models.BooleanField(_(u"register"), |
1474
|
|
|
default=False) |
1475
|
|
|
proxy = models.CharField(_(u"proxy"), |
1476
|
|
|
max_length=48, |
1477
|
|
|
default="", |
1478
|
|
|
help_text=_(u"IP if register is False.")) |
1479
|
|
|
SIP_TRANSPORT_CHOICES = ( |
1480
|
|
|
("udp", _(u"UDP")), |
1481
|
|
|
("tcp", _(u"TCP")), |
1482
|
|
|
("tls", _(u"TLS")), |
1483
|
|
|
) |
1484
|
|
|
transport = models.CharField(_(u"SIP transport"), |
1485
|
|
|
max_length=15, |
1486
|
|
|
default="udp", |
1487
|
|
|
choices=SIP_TRANSPORT_CHOICES, |
1488
|
|
|
help_text=_(u"Which transport to use for register")) |
1489
|
|
|
sip_port = models.PositiveIntegerField( |
1490
|
|
|
_(u"""SIP port"""), |
1491
|
|
|
default="5060", |
1492
|
|
|
help_text=_(u"""Gateway SIP port (Default 5060).""")) |
1493
|
|
|
extension = models.CharField(_(u"extension number"), |
1494
|
|
|
max_length=50, |
1495
|
|
|
blank=True, |
1496
|
|
|
default="", |
1497
|
|
|
help_text=_(u"""Extension for inbound calls. |
1498
|
|
|
Same as username, if blank.""")) |
1499
|
|
|
realm = models.CharField(_(u"realm"), |
1500
|
|
|
max_length=50, |
1501
|
|
|
blank=True, |
1502
|
|
|
default="", |
1503
|
|
|
help_text=_(u"""Authentication realm. Same as |
1504
|
|
|
gateway name, if blank.""")) |
1505
|
|
|
from_domain = models.CharField(_(u"from domain"), |
1506
|
|
|
max_length=50, |
1507
|
|
|
blank=True, |
1508
|
|
|
default="", |
1509
|
|
|
help_text=_(u"""Domain to use in from field. |
1510
|
|
|
Same as realm if blank.""")) |
1511
|
|
|
expire_seconds = models.PositiveIntegerField(_(u"expire seconds"), |
1512
|
|
|
default=3600, |
1513
|
|
|
null=True) |
1514
|
|
|
retry_seconds = models.PositiveIntegerField(_(u"retry seconds"), |
1515
|
|
|
default=30, |
1516
|
|
|
null=True, |
1517
|
|
|
help_text=_(u"""How many |
1518
|
|
|
seconds before a retry when |
1519
|
|
|
a failure or timeout occurs |
1520
|
|
|
""")) |
1521
|
|
|
caller_id_in_from = models.BooleanField(_(u"caller ID in From field"), |
1522
|
|
|
default=True, |
1523
|
|
|
help_text=_(u"""Use the callerid of |
1524
|
|
|
an inbound call in the from |
1525
|
|
|
field on outbound calls via |
1526
|
|
|
this gateway.""")) |
1527
|
|
|
SIP_CID_TYPE_CHOICES = ( |
1528
|
|
|
('none', _(u'none')), |
1529
|
|
|
('default', _(u'default')), |
1530
|
|
|
('pid', _(u'pid')), |
1531
|
|
|
('rpid', _(u'P-Asserted-Identity')), |
1532
|
|
|
) |
1533
|
|
|
sip_cid_type = models.CharField(_(u'SIP CID type'), |
1534
|
|
|
max_length=10, |
1535
|
|
|
choices=SIP_CID_TYPE_CHOICES, |
1536
|
|
|
default='rpid', |
1537
|
|
|
help_text=_(u"""Modify callerID in SIP |
1538
|
|
|
Headers.""")) |
1539
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
1540
|
|
|
auto_now_add=True) |
1541
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
1542
|
|
|
auto_now=True) |
1543
|
|
|
|
1544
|
|
|
class Meta: |
1545
|
|
|
db_table = 'sofia_gateway' |
1546
|
|
|
app_label = 'pyfreebill' |
1547
|
|
|
ordering = ('company', 'name') |
1548
|
|
|
verbose_name = _(u"Sofia gateway") |
1549
|
|
|
verbose_name_plural = _(u"Sofia gateways") |
1550
|
|
|
|
1551
|
|
|
def __unicode__(self): |
1552
|
|
|
return u"%s" % self.name |
1553
|
|
|
|
1554
|
|
|
# Hangup Cause |
1555
|
|
|
|
1556
|
|
|
|
1557
|
|
|
class HangupCause(models.Model): |
1558
|
|
|
""" Hangup Cause Model """ |
1559
|
|
|
code = models.PositiveIntegerField(_(u"Hangup code"), |
1560
|
|
|
unique=True, |
1561
|
|
|
help_text=_(u"ITU-T Q.850 Code.")) |
1562
|
|
|
enumeration = models.CharField(_(u"enumeration"), |
1563
|
|
|
max_length=100, |
1564
|
|
|
null=True, |
1565
|
|
|
blank=True, |
1566
|
|
|
help_text=_(u"enumeration.")) |
1567
|
|
|
cause = models.CharField(_(u"cause"), |
1568
|
|
View Code Duplication |
max_length=100, |
|
|
|
|
1569
|
|
|
null=True, |
1570
|
|
|
blank=True, |
1571
|
|
|
help_text=_(u"Cause.")) |
1572
|
|
|
description = models.TextField(_(u'description'), |
1573
|
|
|
blank=True) |
1574
|
|
|
date_added = models.DateTimeField(_(u'date added'), |
1575
|
|
|
auto_now_add=True) |
1576
|
|
|
date_modified = models.DateTimeField(_(u'date modified'), |
1577
|
|
|
auto_now=True) |
1578
|
|
|
|
1579
|
|
|
class Meta: |
1580
|
|
|
db_table = 'hangup_cause' |
1581
|
|
|
app_label = 'pyfreebill' |
1582
|
|
|
ordering = ('code',) |
1583
|
|
|
verbose_name = _(u"hangupcause") |
1584
|
|
|
verbose_name_plural = _(u"hangupcauses") |
1585
|
|
|
|
1586
|
|
|
def __unicode__(self): |
1587
|
|
|
return u"[%s] %s" % (self.code, self.enumeration) |
1588
|
|
|
|
1589
|
|
|
# STATS |
1590
|
|
|
|
1591
|
|
|
|
1592
|
|
|
class DimDate(models.Model): |
1593
|
|
|
""" Date dimension """ |
1594
|
|
|
date = models.DateTimeField() |
1595
|
|
|
day = models.CharField(_(u'day'), max_length=2) |
1596
|
|
|
day_of_week = models.CharField(_(u'day of the week'), max_length=30) |
1597
|
|
|
hour = models.CharField(_(u'hour'), max_length=2, null=True, blank=True) |
1598
|
|
|
month = models.CharField(_(u'month'), max_length=2) |
1599
|
|
|
quarter = models.CharField(_(u'quarter'), max_length=2) |
1600
|
|
|
year = models.CharField(_(u'year'), max_length=4) |
1601
|
|
|
|
1602
|
|
|
class Meta: |
1603
|
|
View Code Duplication |
db_table = 'date_dimension' |
|
|
|
|
1604
|
|
|
app_label = 'pyfreebill' |
1605
|
|
|
ordering = ('date',) |
1606
|
|
|
verbose_name = _(u"date dimension") |
1607
|
|
|
verbose_name_plural = _(u"date dimensions") |
1608
|
|
|
|
1609
|
|
|
def __unicode__(self): |
1610
|
|
|
return u"%s" % self.date |
1611
|
|
|
|
1612
|
|
|
|
1613
|
|
|
class DimCustomerHangupcause(models.Model): |
1614
|
|
|
""" Dimension Customer / Hangupcause Model """ |
1615
|
|
|
customer = models.ForeignKey(Company, verbose_name=_(u"customer")) |
1616
|
|
|
destination = models.CharField(_(u'destination'), max_length=250, null=True, blank=True) |
1617
|
|
|
hangupcause = models.CharField(_(u'hangupcause'), max_length=100, null=True, blank=True) |
1618
|
|
|
date = models.ForeignKey(DimDate, verbose_name=_(u"date")) |
1619
|
|
|
total_calls = models.IntegerField(_(u"total calls")) |
1620
|
|
|
|
1621
|
|
|
class Meta: |
1622
|
|
|
db_table = 'dim_customer_hangupcause' |
1623
|
|
|
app_label = 'pyfreebill' |
1624
|
|
|
ordering = ('date', 'customer', 'hangupcause') |
1625
|
|
|
verbose_name = _(u"Customer Hangupcause stats") |
1626
|
|
|
verbose_name_plural = _(u"Customer Hangupcause stats") |
1627
|
|
|
|
1628
|
|
|
def __unicode__(self): |
1629
|
|
|
return u"%s -c: %s -h: %s" % (self.date, self.customer, self.hangupcause) |
1630
|
|
View Code Duplication |
|
|
|
|
|
1631
|
|
|
|
1632
|
|
|
class DimCustomerSipHangupcause(models.Model): |
1633
|
|
|
""" Dimension Customer / SIP Hangupcause Model """ |
1634
|
|
|
customer = models.ForeignKey(Company, verbose_name=_(u"customer")) |
1635
|
|
|
destination = models.CharField(_(u'destination'), max_length=250, null=True, blank=True) |
1636
|
|
|
sip_hangupcause = models.CharField(_(u'sip hangupcause'), max_length=100, null=True, blank=True) |
1637
|
|
|
date = models.ForeignKey(DimDate, verbose_name=_(u"date")) |
1638
|
|
|
total_calls = models.IntegerField(_(u"total calls")) |
1639
|
|
|
|
1640
|
|
|
class Meta: |
1641
|
|
|
db_table = 'dim_customer_sip_hangupcause' |
1642
|
|
|
app_label = 'pyfreebill' |
1643
|
|
|
ordering = ('date', 'customer', 'sip_hangupcause') |
1644
|
|
|
verbose_name = _(u"Customer SIP Hangupcause stats") |
1645
|
|
|
verbose_name_plural = _(u"Customer SIP Hangupcause stats") |
1646
|
|
|
|
1647
|
|
|
def __unicode__(self): |
1648
|
|
|
return u"%s -c: %s -h: %s" % (self.date, self.customer, self.sip_hangupcause) |
1649
|
|
View Code Duplication |
|
|
|
|
|
1650
|
|
|
|
1651
|
|
|
class DimProviderHangupcause(models.Model): |
1652
|
|
|
""" Dimension Provider / Hangupcause Model """ |
1653
|
|
|
provider = models.ForeignKey(Company, verbose_name=_(u"provider")) |
1654
|
|
|
destination = models.CharField(_(u'destination'), max_length=250, null=True, blank=True) |
1655
|
|
|
hangupcause = models.CharField(_(u'hangupcause'), max_length=100, null=True, blank=True) |
1656
|
|
|
date = models.ForeignKey(DimDate, verbose_name=_(u"date")) |
1657
|
|
|
total_calls = models.IntegerField(_(u"total calls")) |
1658
|
|
|
|
1659
|
|
|
class Meta: |
1660
|
|
|
db_table = 'dim_provider_hangupcause' |
1661
|
|
|
app_label = 'pyfreebill' |
1662
|
|
|
ordering = ('date', 'provider', 'hangupcause') |
1663
|
|
|
verbose_name = _(u"Provider Hangupcause stats") |
1664
|
|
|
verbose_name_plural = _(u"Provider Hangupcause stats") |
1665
|
|
|
|
1666
|
|
|
def __unicode__(self): |
1667
|
|
|
return u"%s -c: %s -h: %s" % (self.date, self.provider, self.hangupcause) |
1668
|
|
View Code Duplication |
|
|
|
|
|
1669
|
|
|
|
1670
|
|
|
class DimProviderSipHangupcause(models.Model): |
1671
|
|
|
""" Dimension Provider / SIP Hangupcause Model """ |
1672
|
|
|
provider = models.ForeignKey(Company, verbose_name=_(u"provider")) |
1673
|
|
|
destination = models.CharField(_(u'destination'), max_length=250, null=True, blank=True) |
1674
|
|
|
sip_hangupcause = models.CharField(_(u'sip hangupcause'), max_length=100, null=True, blank=True) |
1675
|
|
|
date = models.ForeignKey(DimDate, verbose_name=_(u"date")) |
1676
|
|
|
total_calls = models.IntegerField(_(u"total calls")) |
1677
|
|
|
|
1678
|
|
|
class Meta: |
1679
|
|
|
db_table = 'dim_provider_sip_hangupcause' |
1680
|
|
|
app_label = 'pyfreebill' |
1681
|
|
|
ordering = ('date', 'provider', 'sip_hangupcause') |
1682
|
|
|
verbose_name = _(u"Provider SIP Hangupcause stats") |
1683
|
|
|
verbose_name_plural = _(u"Provider SIP Hangupcause stats") |
1684
|
|
|
|
1685
|
|
|
def __unicode__(self): |
1686
|
|
|
return u"%s -c: %s -h: %s" % (self.date, self.provider, self.sip_hangupcause) |
1687
|
|
View Code Duplication |
|
|
|
|
|
1688
|
|
|
|
1689
|
|
|
class DimCustomerDestination(models.Model): |
1690
|
|
|
""" Dimension Customer / Destination Model """ |
1691
|
|
|
customer = models.ForeignKey(Company, verbose_name=_(u"customer")) |
1692
|
|
|
destination = models.CharField(_(u'destination'), max_length=250, null=True, blank=True) |
1693
|
|
|
date = models.ForeignKey(DimDate, verbose_name=_(u"date")) |
1694
|
|
|
total_calls = models.IntegerField(_(u"total calls"), default=0) |
1695
|
|
|
success_calls = models.IntegerField(_(u"success calls"), default=0) |
1696
|
|
|
total_duration = models.IntegerField(_(u"total duration"), default=0) |
1697
|
|
|
avg_duration = models.IntegerField(_(u"average duration"), default=0) |
1698
|
|
|
max_duration = models.IntegerField(_(u"max duration"), default=0) |
1699
|
|
|
min_duration = models.IntegerField(_(u"min duration"), default=0) |
1700
|
|
|
total_sell = models.DecimalField(_(u'total sell'), max_digits=12, decimal_places=2) |
1701
|
|
|
total_cost = models.DecimalField(_(u'total cost'), max_digits=12, decimal_places=2) |
1702
|
|
|
|
1703
|
|
|
class Meta: |
1704
|
|
|
db_table = 'dim_customer_destination' |
1705
|
|
|
app_label = 'pyfreebill' |
1706
|
|
|
ordering = ('date', 'customer', 'destination') |
1707
|
|
|
verbose_name = _(u"Customer destination stats") |
1708
|
|
|
verbose_name_plural = _(u"Customer destination stats") |
1709
|
|
|
|
1710
|
|
|
def __unicode__(self): |
1711
|
|
|
return u"%s -c: %s -d: %s" % (self.date, self.customer, self.destination) |
1712
|
|
|
|
1713
|
|
|
def _get_margin(self): |
1714
|
|
|
if self.total_sell and self.total_cost: |
1715
|
|
|
margin = self.total_sell - self.total_cost |
1716
|
|
|
else: |
1717
|
|
|
margin = 0 |
1718
|
|
|
return round(margin, 2) |
1719
|
|
|
margin = property(_get_margin) |
1720
|
|
|
|
1721
|
|
|
|
1722
|
|
|
class SaleSummary(DimCustomerDestination): |
1723
|
|
|
class Meta: |
1724
|
|
|
proxy = True |
1725
|
|
|
verbose_name = 'Sale Summary' |
1726
|
|
|
verbose_name_plural = 'Sales Summary' |
1727
|
|
|
|
1728
|
|
|
|
1729
|
|
|
class DimProviderDestination(models.Model): |
1730
|
|
|
""" Dimension Provider / Destination Model """ |
1731
|
|
|
provider = models.ForeignKey(Company, verbose_name=_(u"provider")) |
1732
|
|
|
destination = models.CharField(_(u'destination'), max_length=250, null=True, blank=True) |
1733
|
|
|
date = models.ForeignKey(DimDate, verbose_name=_(u"date")) |
1734
|
|
|
total_calls = models.IntegerField(_(u"total calls"), default=0) |
1735
|
|
|
success_calls = models.IntegerField(_(u"success calls"), default=0) |
1736
|
|
|
total_duration = models.IntegerField(_(u"total duration"), default=0) |
1737
|
|
|
avg_duration = models.IntegerField(_(u"average duration"), default=0) |
1738
|
|
|
max_duration = models.IntegerField(_(u"max duration"), default=0) |
1739
|
|
|
min_duration = models.IntegerField(_(u"min duration"), default=0) |
1740
|
|
|
total_sell = models.DecimalField(_(u'total sell'), max_digits=12, decimal_places=2) |
1741
|
|
|
total_cost = models.DecimalField(_(u'total cost'), max_digits=12, decimal_places=2) |
1742
|
|
|
|
1743
|
|
|
class Meta: |
1744
|
|
|
db_table = 'dim_provider_destination' |
1745
|
|
|
app_label = 'pyfreebill' |
1746
|
|
|
ordering = ('date', 'provider', 'destination') |
1747
|
|
|
verbose_name = _(u"Provider destination stats") |
1748
|
|
|
verbose_name_plural = _(u"Provider destination stats") |
1749
|
|
|
|
1750
|
|
|
def __unicode__(self): |
1751
|
|
|
return u"%s -p: %s -d: %s" % (self.date, self.provider, self.destination) |
1752
|
|
|
|
1753
|
|
|
def get_daily_providers_stats(self, today, delta, interval): |
1754
|
|
|
qs = self.model._default_manager.filter(date__lte=lastday) |
1755
|
|
|
qss = qsstats.QuerySetStats(qs, 'date') |
1756
|
|
|
lastday = today - datetime.timedelta(days=delta) |
1757
|
|
|
return qss.time_series(lastday, today, interval) |
1758
|
|
|
|
1759
|
|
|
def get_current_week_daily_provider_stats(self, period, interval): |
1760
|
|
|
today = datetime.date.today() |
1761
|
|
|
return self.get_daily_providers_stats(today, period, interval) |
1762
|
|
|
|
1763
|
|
|
def get_day_total_calls(self): |
1764
|
|
|
qs = DimProviderDestination.objects.all() |
1765
|
|
|
day_qs = qs.values('date').annotate(day_total_calls=Sum('total_calls'), day_success_calls=Sum('success_calls'), day_total_duration=Sum('total_duration'), day_total_sell=Sum('total_sell'), day_total_cost=Sum('total_cost')).order_by('date') |
1766
|
|
|
return [t[1] for t in day_qs] |
1767
|
|
|
|
1768
|
|
|
|
1769
|
|
|
class CostSummary(DimProviderDestination): |
1770
|
|
|
class Meta: |
1771
|
|
|
proxy = True |
1772
|
|
|
verbose_name = 'Cost Summary' |
1773
|
|
|
verbose_name_plural = 'Cost Summary' |
1774
|
|
|
|