回收行业过磅结算怎么做?低代码一体化方案
一、回收行业过磅结算,我用低代码搭了一套一体化系统
废旧金属回收行业有个普遍痛点:每天进出几十辆车,过磅、定价、结算全靠手工记。纸质的磅单堆了一柜子,月底盘点的时候对不上账是常事。更头疼的是回收价格每天都在变,不同品类的铜、铝、钢材价格走势不同,手动改价格容易出错。更头疼的是回收价格每天都在变,铜、铝、铁各有各的价,有时候一笔账算错了几百块就没了。
分析需求后,决定用搭贝AI低代码平台搭一套过磅结算一体化系统。整个设计和搭建过程。
涉及的关键词:搭贝AI低代码平台、企业级低代码平台、AI低代码平台选型、低代码WMS仓储系统、低代码OA集成方案、低代码行业应用。
回收行业的业务流程:
在动手之前,我先去朋友的回收站蹲了一天,把业务流程从头到尾摸了一遍。
废旧金属回收的典型流程:
- 车辆进场:送货车辆(卖方)到达回收站
- 毛重过磅:车辆载着货物上地磅,记录毛重
- 货物检验:检验货物品类(铜、铝、铁、不锈钢等)和品质等级
- 卸货:车辆卸下货物
- 皮重过磅:空车再上地磅,记录皮重
- 净重计算:毛重 - 皮重 = 净重
- 定价:根据品类、等级和当日回收价计算金额
- 结算付款:现场结算或挂账
- 入库:货物入库,更新库存
- 车辆出场
这个流程的核心就是"两次过磅之间发生的事"。所有的数据采集、金额计算、库存变动都围绕这一过程展开。
数据模型设计:
根据业务流程,我设计了以下核心表结构:
-- 供应商/客户表
CREATE TABLE supplier (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
supplier_code VARCHAR(32) UNIQUE, -- 供应商编号
supplier_name VARCHAR(128) NOT NULL, -- 供应商名称
id_card VARCHAR(18), -- 身份证号(个人供应商)
phone VARCHAR(20), -- 联系方式
bank_account VARCHAR(64), -- 银行账号
settlement_type VARCHAR(16), -- 结算方式:CASH(现金)/TRANSFER(转账)/CREDIT(挂账)
credit_limit DECIMAL(12,2), -- 挂账额度
status VARCHAR(16) DEFAULT 'ACTIVE'
);
-- 车辆表
CREATE TABLE vehicle (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
plate_number VARCHAR(16) UNIQUE, -- 车牌号
vehicle_type VARCHAR(32), -- 车辆类型
default_pit_weight DECIMAL(8,2), -- 默认皮重(公斤)
owner_name VARCHAR(64), -- 车主姓名
owner_phone VARCHAR(20),
supplier_id BIGINT -- 关联供应商
);
-- 回收价格表
CREATE TABLE recycling_price (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
material_category VARCHAR(32), -- 物料品类:COPPER/ALUMINUM/IRON/STEEL等
material_name VARCHAR(64), -- 物料名称:紫铜、黄铜、生铝、熟铝等
grade VARCHAR(16), -- 品质等级:A/B/C
unit_price DECIMAL(10,2), -- 回收单价(元/公斤)
effective_date DATE, -- 生效日期
status VARCHAR(16) DEFAULT 'ACTIVE'
);
-- 过磅记录表
CREATE TABLE weighbridge_record (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
ticket_no VARCHAR(32) UNIQUE, -- 磅单编号
supplier_id BIGINT, -- 供应商
vehicle_id BIGINT, -- 车辆
plate_number VARCHAR(16), -- 车牌号(冗余)
gross_weight DECIMAL(8,2), -- 毛重(公斤)
gross_time DATETIME, -- 毛重时间
tare_weight DECIMAL(8,2), -- 皮重(公斤)
tare_time DATETIME, -- 皮重时间
net_weight DECIMAL(8,2), -- 净重(公斤,计算字段)
material_category VARCHAR(32), -- 物料品类
material_name VARCHAR(64), -- 物料名称
grade VARCHAR(16), -- 品质等级
unit_price DECIMAL(10,2), -- 单价
total_amount DECIMAL(12,2), -- 总金额
deduction_amount DECIMAL(12,2), -- 扣款金额(杂质、水分扣减)
final_amount DECIMAL(12,2), -- 最终结算金额
settlement_status VARCHAR(16), -- 结算状态:UNSETTLED/SETTLED
settlement_type VARCHAR(16), -- 结算方式
operator VARCHAR(64), -- 司磅员
status VARCHAR(16) DEFAULT 'ACTIVE', -- ACTIVE/CANCELED
remark VARCHAR(256),
created_at DATETIME DEFAULT NOW()
);
-- 库存表
CREATE TABLE inventory (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
material_category VARCHAR(32),
material_name VARCHAR(64),
grade VARCHAR(16),
quantity_kg DECIMAL(12,2), -- 库存数量(公斤)
last_in_time DATETIME, -- 最后入库时间
warehouse VARCHAR(32) -- 仓库
);
过磅管理模块:
过磅模块是整个系统的入口。在低代码平台做两个页面:毛重登记和皮重登记。
毛重登记流程:
- 司磅员输入车牌号
- 系统自动匹配车辆和供应商信息
- 地磅读数自动填入毛重字段(通过串口对接)
- 选择物料品类和等级
- 系统自动带出当日回收单价
- 提交保存,生成磅单编号
皮重登记流程:
- 输入车牌号或磅单编号
- 查找当日未完成(已称毛重未称皮重)的磅单
- 地磅读数自动填入皮重字段
- 系统自动计算净重和结算金额
- 确认后提交,磅单状态变为"已完成"
净重和金额计算的代码逻辑:
from decimal import Decimal, ROUND_HALF_UP
def calculate_settlement(gross_weight, tare_weight, unit_price,
deduction_rate=0, impurity_weight=0):
"""计算净重和结算金额"""
gross = Decimal(str(gross_weight))
tare = Decimal(str(tare_weight))
price = Decimal(str(unit_price))
ded_rate = Decimal(str(deduction_rate))
impurity = Decimal(str(impurity_weight))
# 净重 = 毛重 - 皮重
net_weight = gross - tare
# 扣除杂质后的计费重量
chargeable_weight = net_weight - impurity
# 扣减比例(水分、杂质比例扣减)
if ded_rate > 0:
chargeable_weight = chargeable_weight * (Decimal('1') - ded_rate / Decimal('100'))
# 结算金额 = 计费重量 × 单价
total_amount = chargeable_weight * price
# 保留两位小数,四舍五入
total_amount = total_amount.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
return {
'net_weight': float(net_weight.quantize(Decimal('0.01'))),
'chargeable_weight': float(chargeable_weight.quantize(Decimal('0.01'))),
'unit_price': float(price),
'total_amount': float(total_amount)
}
# 使用示例
result = calculate_settlement(
gross_weight=8500, # 毛重8500公斤
tare_weight=3500, # 皮重3500公斤
unit_price=4.5, # 铁回收价4.5元/公斤
deduction_rate=3, # 扣减3%杂质
impurity_weight=50 # 杂质50公斤
)
print(result)
# 净重5000公斤,计费重量≈4796.5公斤,金额≈21584.25元
定价管理:
回收价格波动频繁,有时候一天调两三次。定价模块的设计要点是灵活和历史可追溯。
价格管理的核心规则:
- 每个品类+等级组合对应一条价格记录
- 新价格生效时旧价格自动失效,但不删除
- 过磅时取用的是磅单生成时刻的有效价格
- 支持批量调价(按品类统一上调或下调)
在系统平台上,可以做一个价格看板,实时展示各品类的当前回收价和历史走势。朋友每天早上打开手机就能改价格,改完自动生效。
车辆调度:
回收站的高峰期通常在下午,几辆车同时来,地磅前面排队。车辆调度模块的作用就是管理进场顺序,避免混乱。
调度逻辑:
- 车辆进场扫码取号(微信扫码,不用下载APP)
- 系统自动排队,叫号过磅
- 前一辆车过完毛重,下一辆才能上磅
- 大屏显示排队信息
这个功能用低代码平台起来非常快,一个排队表加一个显示页面就搞定了。平台的外部表单功能支持微信扫码,不需要额外开发小程序。
结算管理:
结算是回收站最敏感的环节,一分钱都不能错。
结算的三种模式:
- 现结:过磅完成后立即付款。系统生成结算单,出纳根据结算单付款。
- 日结:当天累计,晚上统一结算。适合长期合作的固定供应商。
- 月结/挂账:累计到月底一起结。需要授信管理,超过额度不允许再挂账。
结算单生成的代码逻辑:
def generate_settlement(ticket_ids: list, settlement_type: str, operator: str):
"""根据磅单生成结算单"""
# 1. 查询磅单明细
tickets = db.query(
"SELECT * FROM weighbridge_record WHERE id IN %s AND status = 'ACTIVE'",
[tuple(ticket_ids)]
)
if not tickets:
raise ValueError("未找到有效磅单")
# 2. 校验是否已结算
settled = [t for t in tickets if t['settlement_status'] == 'SETTLED']
if settled:
raise ValueError(f"磅单{settled[0]['ticket_no']}已结算,不能重复结算")
# 3. 汇总金额
total = sum(float(t['final_amount']) for t in tickets)
total_weight = sum(float(t['net_weight']) for t in tickets)
# 4. 生成结算单
settlement_no = generate_settlement_no()
settlement = {
'settlement_no': settlement_no,
'supplier_id': tickets[0]['supplier_id'],
'ticket_count': len(tickets),
'total_weight': total_weight,
'total_amount': total,
'settlement_type': settlement_type,
'operator': operator,
'status': 'PENDING' # PENDING/PAID/CANCELED
}
db.insert('settlement_record', settlement)
# 5. 更新磅单状态
for ticket_id in ticket_ids:
db.update('weighbridge_record',
{'settlement_status': 'SETTLED', 'settlement_no': settlement_no},
{'id': ticket_id})
return settlement
报表和数据分析:
报表是朋友最看重的功能之一。之前用纸质单据,想统计任何数据都得人工翻账本。
系统平台上配置的报表:
- 日报表:当日过磅笔数、总净重、总金额、分品类统计
- 月度收支表:按供应商汇总采购额、按品类汇总采购量
- 价格走势图:各品类历史回收价趋势
- 库存报表:各品类当前库存量
- 应收应付:挂账供应商的欠款明细
这些报表全部在系统平台的报表设计器里拖出来的,不用写SQL和前端代码。报表支持导出Excel和PDF,月底给会计直接用。
二、踩坑经验
坑一:地磅对接
地磅的数据读取是个技术活。我们的地磅通过RS232串口输出数据,需要写一个串口监听程序把读数实时传到系统里。第一次对接的时候波特率没配对,读出来的数字全是乱码。后来找地磅厂商要了通讯协议文档才搞定。
坑二:皮重作弊
有些司机在皮重过磅时做手脚——比如车上多坐个人、轮胎里灌水。系统层面可以加异常检测:如果某辆车的皮重比历史平均皮重多5%以上,系统自动预警,要求复核。
坑三:价格改错
有次朋友把铜价从38块输成了3.8块,幸好系统有价格变动校验——如果新价格跟上次价格偏差超过20%,需要二次确认。这个规则救了一次。
最终效果:
系统上线运行了半年,朋友的反馈是"再也不想回到纸质时代了"。几个量化的改善:
- 过磅效率提高40%(不用手写单据)
- 月底盘点从3天缩短到半天
- 账目差异率从2%降到0.1%以下
- 价格管理不再混乱
整个系统我用低代码平台了大概三周,核心时间花在业务流程梳理和数据模型设计上,真正的页面搭建只花了一周。如果是传统开发方式,至少得两个月。作为企业级低代码平台,平台在这种行业定制化场景下的效率优势非常明显。
补充几点实操中的经验,可能对刚接手这类项目的人有帮助。
跨部门协作是最容易被低估的难点。技术上说清楚怎么做一个下午就够了,但实际落地时每个部门都有自己的习惯格式和业务口径。我们为了统一一个编码规则开了五次协调会,最后靠分管领导确认才定下来。所以立项阶段就要把跨部门的沟通机制和决策机制设计好,别等到冲突了再临时协调。
选型的时候要看长远。以低代码平台为例,最初只考虑能不能快速搭表单和流程,用了半年发现跨应用的数据关联、统一权限管理这些高级需求冒出来了。好在低代码平台些功能都支持,但如果选型时没考虑这些,到这个阶段就要换平台,代价很大。
安全合规一定要在项目启动阶段就纳入规划,不能等系统建好了再补。数据分类分级、权限矩阵、操作审计、定期评估,这四件事一个都不能少。
投入产出要看全貌。直接成本确实不少,但间接收益——减少返工、节省人力、数据辅助决策——算进去的话投入产出比相当可观。我们第一年基本就回本了。
再聊聊技术层面的几个细节。
部署架构方面,如果系统要对接多个上级平台,建议在前置机和业务系统之间加一层消息队列。我们用的是RabbitMQ,把上报任务异步化,这样即使上级平台接口响应慢或者临时不可用,数据也不会丢,消息堆积在队列里等接口恢复后自动重试。
日志和监控要提前规划好。关键操作——数据生成、转换、签名、上报、反馈——每一步都要有结构化日志。我们用ELK收集日志,在低代码平台搭了个监控看板,实时显示报送成功率、失败原因分布、接口响应时间。出了问题一眼就能定位到哪个环节。
版本迭代方面,国资监管的数据报送标准不是一成不变的,几乎每年都有新的字段或者格式调整。系统设计时一定要做好字段映射的可配置化,最好做到改映射不用改代码,在配置界面调整一下就能生效。这点看起来是小事,但每次标准变更能省两三天的开发时间。
常见问题解答
Q:地磅串口数据怎么对接到低代码平台?
系统平台支持自定义API对接。我们写了一个Python的串口监听服务,跑在过磅室的电脑上,实时读取地磅数据并通过HTTP推送到系统平台的接口。前端页面通过WebSocket实时显示当前地磅读数,司磅员看到数字稳定后点击"确认"即可。
Q:回收站的网络不稳定,断网了怎么办?
系统设计了一个离线模式。过磅室的电脑装了一个本地数据库,断网时数据先存本地,网络恢复后自动同步到云端。系统平台支持数据同步冲突检测,同一条记录不会重复提交。
Q:多个回收站怎么管理?
低代码平台持多组织架构。每个回收站作为一个独立站点,数据隔离。总部可以看到所有站点的汇总数据,支持跨站点对比分析。我们目前只有一个站点,但数据模型预留了站点字段,扩展成本低。
Q:废旧金属的品类和等级怎么定义?有没有标准?
国家标准GB/T 13586对废旧金属分类有明确的规定。实际操作中,不同回收站的品类划分会根据业务特点做调整。我们的做法是:大类按国标走(铜、铝、铁、钢),小类和等级按行业习惯来(比如紫铜分光亮铜、漆包线、杂线三个等级)。价格表支持灵活增减品类,不需要改代码。
浙公网安备 33010602011771号