本文用于指导客服或实施人员配置“台湾报关文件自动上传”规则。配置完成后,客户在已绑定的企业微信群发送合格的 Excel 报关文件,系统会自动查找对应运单;没有匹配运单时自动创建预报运单,再把原始 Excel 上传到“报关文件”档案。
台湾报关自动处理面向所有已开通易信达并满足下方配置条件的机构,无需另行申请开通台湾报关专用能力。
一条合格文件消息进入系统后,规则会依次完成:
xls 或 xlsx,并符合台湾报关文件特征。上传成功后即结束,不会自动生成清关文件、公司汇总报关文件或销仓文件。如需生成这些文件,仍使用小易处理台湾报关资料。
配置前逐项确认:
规则会一直以创建人的当前账号权限执行。创建人被禁用、离职或权限被收回后,规则会执行失败,因此不要使用临时账号创建正式规则。
进入“基础数据”,选择“易信达消息自动化”,点击“新建”。

建议填写:
台湾报关文件自动上传
把下面完整公式复制到“触发条件”:
是否群聊消息()
&& 是否文件消息()
&& 是否为指定文件扩展名('xls', 'xlsx')
&& 是否台湾报关文件()
这段公式只让企业微信群里的台湾报关 Excel 文件进入执行脚本。是否台湾报关文件() 是本业务的专用函数。由于这类业务使用范围较小,页面的通用函数帮助不列出它;需要配置时以本文中的公式和说明为准。
把下面完整脚本复制到“执行脚本”:
(() => {
'use strict';
const CHANNEL_RULES = Object.freeze([
Object.freeze({ keywords: Object.freeze(['HK', '香港']), channelName: 'HK空运普通货/特货' }),
Object.freeze({ keywords: Object.freeze(['澳门']), channelName: '澳门-台湾空运普货' }),
Object.freeze({ keywords: Object.freeze(['中港']), channelName: '中港费' }),
Object.freeze({ keywords: Object.freeze(['中澳']), channelName: '中澳费' })
]);
function normalizeText(value) {
return value === null || value === undefined ? '' : String(value).trim();
}
function resolveReceiveChannelName(sourceChannelValues) {
if (!Array.isArray(sourceChannelValues) || sourceChannelValues.length === 0) {
throw new Error('报关文件没有可用的收货渠道');
}
const mappedChannelNames = [];
for (let sourceIndex = 0; sourceIndex < sourceChannelValues.length; sourceIndex += 1) {
var sourceText = normalizeText(sourceChannelValues[sourceIndex]);
if (sourceText === '') {
throw new Error('报关文件存在空白收货渠道');
}
var normalizedSource = sourceText.toUpperCase();
var matchedRules = CHANNEL_RULES.filter(rule =>
rule.keywords.some(keyword => normalizedSource.includes(keyword.toUpperCase()))
);
if (matchedRules.length === 0) {
throw new Error(`收货渠道“${sourceText}”没有配置台湾报关映射`);
}
if (matchedRules.length > 1) {
throw new Error(`收货渠道“${sourceText}”同时命中多个台湾报关映射`);
}
if (mappedChannelNames.indexOf(matchedRules[0].channelName) === -1) {
mappedChannelNames.push(matchedRules[0].channelName);
}
}
if (mappedChannelNames.length !== 1) {
throw new Error('同一报关文件最终映射到多个系统收货渠道');
}
return mappedChannelNames[0];
}
function assertWaybillMatches(waybill, receiveChannel, document) {
const sameChannel = normalizeText(waybill.receiveChannelId) === ''
? waybill.receiveChannelName === receiveChannel.name
: waybill.receiveChannelId === receiveChannel.id;
if (!sameChannel) {
throw new Error(
`运单实际收货渠道“${waybill.receiveChannelName || ''}”与报关文件映射渠道“${receiveChannel.name}”不一致`
);
}
if (waybill.pieceCount !== document.pieceCount) {
throw new Error(
`运单件数为 ${waybill.pieceCount},报关文件件数为 ${document.pieceCount}`
);
}
}
const document = 解析当前台湾报关文件();
const customerId = 查找当前群最新绑定客户ID();
if (customerId === null) {
throw new Error('当前企业微信群未绑定有效客户');
}
const receiveChannelName = resolveReceiveChannelName(document.sourceChannelValues);
const receiveChannel = 查找客户可用收货渠道(customerId, receiveChannelName);
if (receiveChannel === null) {
throw new Error(`当前客户没有可用的收货渠道“${receiveChannelName}”`);
}
const businessWindow = 计算业务时间窗(
$message.receivedAt,
'19:00',
'Asia/Shanghai'
);
const candidates = 查询运单({
customerId,
businessType: receiveChannel.businessType,
createTimeBegin: businessWindow.beginTime,
createTimeEnd: businessWindow.endTime
});
if (candidates.length > 1) {
throw new Error('同一客户、业务类型和创建时间窗口匹配到多票运单');
}
let waybill = candidates.length === 1 ? candidates[0] : null;
if (waybill !== null) {
assertWaybillMatches(waybill, receiveChannel, document);
}
const shouldUpload = 是否需要上传当前台湾报关文件({
customerId,
receiveChannel,
fileType: 'DECLARATION',
waybill
});
if (!shouldUpload) {
return Object.freeze({
status: 'SKIPPED',
summary: '最新报关文件已存在,无需重复上传'
});
}
if (waybill === null) {
waybill = 创建预报运单({
customerId,
receiveChannel,
forecastedAt: $message.receivedAt,
destinationCountryCode: 'TW',
packageType: 'PARCEL',
taxPaymentType: 'RECIPIENT',
customsDeclarationType: 'OTHER',
pieceCount: document.pieceCount,
pieceWeightKg: document.pieceWeightKg,
receivingRemark: document.receivingRemark
});
}
上传当前消息文件到运单档案({
waybill,
fileType: 'DECLARATION',
remark: '易信达台湾报关文件自动上传'
});
return Object.freeze({
status: 'SUCCEEDED',
summary: `报关文件已上传至运单 ${waybill.systemNumber}`
});
})();
脚本当前使用以下映射:
| 报关文件中的文字包含 | 系统收货渠道 |
|---|---|
HK 或 香港 |
HK空运普通货/特货 |
澳门 |
澳门-台湾空运普货 |
中港 |
中港费 |
中澳 |
中澳费 |
文件中出现多个不同写法没有关系,但所有非空渠道最终必须只映射到同一个系统收货渠道。未命中、一个值同时命中多条规则,或者最终映射到多个渠道时,本次处理会失败。
渠道名称或关键字发生变化时,只修改脚本顶部的 CHANNEL_RULES。修改后会形成规则新版本,应先禁用并使用测试文件验证,不要直接在正式启用状态下试改。
最近结果的常见含义:
失败不会向客户群发送提示,也不会堵住后续消息。客服修正客户绑定、渠道或权限后,可在“历史日志”中对该条失败记录点击“重新执行”,系统会按规则当前版本重新处理这份文件;已经上传过的文件不会重复上传。也可以继续使用原来的手动上传流程。
A → B → A 会依次保留三个版本。检查文件扩展名是否为 xls/xlsx、易信达 APP 的“不收文件”是否关闭,以及该文件是否符合台湾报关文件特征。
检查客户档案联系人管理中的企业微信群名,确保与发送文件时的群名完全一致。群改名后也要同步更新绑定。
先检查文件中的渠道文字是否符合映射,再确认该客户当前报价中存在对应的系统收货渠道。
检查运单是否属于当前客户和业务类型、创建时间是否落在对应的 19:00 业务时间窗、渠道和件数是否一致,以及规则创建人当前是否有权查看和维护该运单。
先在“历史日志”中打开该条记录的详情,根据执行过程和结果说明修正客户绑定、渠道、文件或权限,然后点击“重新执行”。需要立即处理时,也可以从企业微信群下载原文件,按原来的手动流程上传到指定运单。
历史日志只记录命中触发条件的消息。请检查文件扩展名、“不收文件”开关和文件是否符合台湾报关文件特征;不满足触发条件的消息不会留下记录。