电信运营商每天需要处理海量的资费数据,从基础套餐费用到增值业务扣款,从漫游结算到流量超额计费。传统Excel手工记录方式早已无法满足业务需求,这就是为什么我们需要一个专业的电信资费管理系统。这个基于Python+Django的全栈项目,正是为解决这一行业痛点而生。
我去年为某省级运营商实施过类似系统,上线后他们的资费核算效率提升了300%,人工错误率降至0.5%以下。这个开源版本保留了核心功能架构,包含完整的源码、部署文档和开发说明,特别适合两类人群:一是电信行业IT部门需要快速构建内部管理系统,二是想学习企业级Django开发模式的开发者。
系统最核心的价值在于实现了资费管理的全流程自动化——套餐配置、用户计费、账单生成、财务对账等环节全部线上化。举个例子,当用户订购了"99元畅享套餐",系统会自动关联对应的语音、流量、短信额度,并实时计算使用量。超出部分按预设规则阶梯计价,月底自动生成含详细消费清单的电子账单。
为什么选择Django而非Flask或FastAPI?在电信级应用中,三个关键因素决定了这个选择:内置Admin后台、ORM完善度和权限体系。Django Admin只需百行代码就能构建出功能完善的数据管理界面,这对需要频繁调整资费政策的业务场景至关重要。我们甚至基于Admin二次开发出了套餐可视化配置器,产品经理都能直接操作。
数据库设计采用经典的"用户-套餐-消费记录"三层结构。这里有个行业特殊处理:使用DecimalField存储所有金额字段(而非Float),避免浮点运算带来的分币误差。电信行业对0.01元的差额都极其敏感,我们的模型定义是这样的:
python复制class FeePlan(models.Model):
plan_name = models.CharField(max_length=100)
base_fee = models.DecimalField(max_digits=10, decimal_places=2) # 精确到分
call_rate = models.DecimalField(max_digits=6, decimal_places=4) # 每分钟费率
data_rate = models.DecimalField(max_digits=6, decimal_places=4) # 每MB费率
is_active = models.BooleanField(default=True)
核心计费逻辑在services.py中实现,采用策略模式应对多样的计费规则。比如夜间通话优惠、亲情号码免费、流量结转等特殊规则,都封装成独立策略类。计算用户月度消费的主函数如下:
python复制def calculate_monthly_bill(user_id, month):
user = User.objects.get(pk=user_id)
calls = CallRecord.objects.filter(user=user, time__month=month.month)
datas = DataUsage.objects.filter(user=user, date__month=month.month)
base_fee = user.plan.base_fee
call_fee = sum([apply_call_policy(call) for call in calls])
data_fee = sum([apply_data_policy(data) for data in datas])
return {
'base_fee': base_fee,
'call_fee': round(call_fee, 2),
'data_fee': round(data_fee, 2),
'total': round(base_fee + call_fee + data_fee, 2)
}
特别注意:电信行业要求所有计费操作必须记录完整操作日志。我们在每个价格计算步骤都添加了审计日志,这是通过Django的信号机制实现的。
电信系统对稳定性要求极高,我们的部署方案采用:
关键的Nginx配置片段如下:
nginx复制upstream django_app {
server unix:/opt/telecom/gunicorn.sock fail_timeout=0;
}
server {
listen 443 ssl;
server_name billing.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location /static/ {
alias /opt/telecom/static/;
expires 30d;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://django_app;
}
}
电信系统上线最大的挑战是历史数据迁移。我们开发了专门的迁移脚本处理老系统的CSV导出数据,特别注意:
python复制# 示例迁移脚本片段
def clean_phone_number(raw_phone):
phone = re.sub(r'[^0-9]', '', raw_phone)
if phone.startswith('86'):
phone = phone[2:]
return phone[:11] # 取前11位防止脏数据
为避免用户因欠费停机,系统实现了三级余额预警:
这通过Celery定时任务实现,关键代码如下:
python复制@app.task
def check_low_balance():
users = User.objects.filter(balance__lt=50)
for user in users:
if user.balance < 10:
send_urgent_alert(user)
elif user.balance < 50:
send_normal_alert(user)
系统内置基于用户历史消费的智能推荐引擎,使用简单的协同过滤算法:
python复制def recommend_plan(user):
similar_users = find_similar_users(user)
top_plans = Counter(
u.plan for u in similar_users
if u.monthly_spend < user.monthly_spend
).most_common(3)
return [plan for plan, count in top_plans]
Django配置示例:
python复制SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000 # 1年HSTS
我们在用户量达百万级的实例中,通过以下索引使查询性能提升10倍:
python复制class Meta:
indexes = [
models.Index(fields=['user', '-call_time']),
models.Index(fields=['phone_number']),
]
假设要新增"节假日通话免费"规则:
python复制class HolidayCallPolicy:
def apply(self, call):
if call.time.date() in holidays:
return 0
return call.duration * call.base_rate
系统提供RESTful API供移动端调用,使用Django REST Framework实现。关键点是:
API响应示例:
json复制{
"user": "13800138000",
"balance": 125.50,
"current_plan": "99元畅享套餐",
"data_remaining": 1024,
"call_remaining": 500
}
配置Prometheus监控以下指标:
对应的metrics.py定义:
python复制billing_duration = Summary('billing_duration_seconds', 'Time spent billing')
billing_errors = Counter('billing_errors_total', 'Total billing errors')
@billing_duration.time()
def process_billing(user):
try:
# 计费逻辑
except Exception:
billing_errors.inc()
raise
电信系统日志量巨大,我们采用:
日志配置示例:
python复制LOGGING = {
'handlers': {
'elastic': {
'class': 'elasticsearch_handler.ElasticsearchHandler',
'hosts': ['es01:9200'],
'index': 'telecom-logs'
}
}
}
code复制telecom_billing/
├── apps/
│ ├── billing/ # 核心计费逻辑
│ ├── customer/ # 用户管理
│ ├── reporting/ # 报表系统
│ └── api/ # REST接口
├── config/ # 部署配置
├── scripts/ # 运维脚本
└── static/ # 前端资源
特别说明reporting模块的设计:
python复制class BillingTestCase(TestCase):
def test_overage_charges(self):
user = User.objects.create(balance=100)
plan = FeePlan.objects.create(
base_fee=50,
data_rate=0.1,
data_included=1024
)
usage = DataUsage.objects.create(
user=user,
amount=2048,
date=date.today()
)
bill = calculate_bill(user)
self.assertEqual(bill['data_fee'], 102.4) # (2048-1024)*0.1
使用Locust模拟万级用户并发:
python复制class BillingUser(HttpUser):
@task
def query_balance(self):
self.client.get("/api/balance",
headers={"Authorization": f"Bearer {token}"})
@task(3)
def submit_usage(self):
self.client.post("/api/usage",
json={"call_duration": 120},
headers={"Authorization": f"Bearer {token}"})
短期规划:
长期方向:
这个项目最让我自豪的是它的灵活性——从初创虚拟运营商到省级电信公司,通过调整配置就能适配不同规模的需求。在源码的docs/目录下,我特别编写了《电信计费业务知识手册》,帮助开发者理解行业特殊需求。