fix(pre-planting): 签署合同前检查实名认证 + 修正合同金额
- getMergeContractPdf: KYC 为 null 时返回 400,不允许查看合同 - getMergeContractPdf: 从源订单汇总实际绿积分金额,CNY = 绿积分 × 1.1 - Flutter: KYC 错误时显示专用提示 + "去完成实名认证" 按钮 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b1e5e6b29f
commit
cd73b2dec4
|
|
@ -406,10 +406,19 @@ export class PrePlantingApplicationService {
|
|||
return m;
|
||||
});
|
||||
|
||||
// 获取用户 KYC 信息
|
||||
const kycInfo = await this.identityServiceClient.getUserKycInfo(
|
||||
merge.accountSequence,
|
||||
);
|
||||
// 获取用户 KYC 信息 - 未完成实名认证则不允许查看合同
|
||||
const kycInfo = await this.identityServiceClient.getUserKycInfo(merge.accountSequence);
|
||||
if (!kycInfo || !kycInfo.realName) {
|
||||
throw new BadRequestException('请先完成实名认证方可查看和签署合同');
|
||||
}
|
||||
|
||||
// 从源订单汇总实际支付的绿积分金额
|
||||
const sourceOrders = await this.prisma.prePlantingOrder.findMany({
|
||||
where: { orderNo: { in: merge.sourceOrderNos } },
|
||||
select: { totalAmount: true },
|
||||
});
|
||||
const greenPointsAmount = sourceOrders.reduce((sum, o) => sum + o.totalAmount, 0);
|
||||
const totalAmount = Math.round(greenPointsAmount * 1.1 * 100) / 100; // 含税 CNY
|
||||
|
||||
// 生成北京时间日期
|
||||
const now = new Date(Date.now() + 8 * 60 * 60 * 1000);
|
||||
|
|
@ -417,10 +426,12 @@ export class PrePlantingApplicationService {
|
|||
|
||||
return this.pdfGeneratorService.generateContractPdf({
|
||||
contractNo: mergeNo,
|
||||
userRealName: kycInfo?.realName || '未认证',
|
||||
userIdCard: kycInfo?.idCardNumber || '',
|
||||
userPhone: kycInfo?.phoneNumber || '',
|
||||
userRealName: kycInfo.realName,
|
||||
userIdCard: kycInfo.idCardNumber || '',
|
||||
userPhone: kycInfo.phoneNumber || '',
|
||||
treeCount: merge.treeCount,
|
||||
totalAmount,
|
||||
greenPointsAmount,
|
||||
signingDate,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart';
|
|||
import 'package:path_provider/path_provider.dart';
|
||||
import '../../../../core/di/injection_container.dart';
|
||||
import '../../../../core/services/pre_planting_service.dart';
|
||||
import '../../../../routes/route_paths.dart';
|
||||
import '../../../contract_signing/presentation/widgets/signature_pad.dart';
|
||||
|
||||
/// 预种合并合同签署页面
|
||||
|
|
@ -38,6 +39,7 @@ class _PrePlantingMergeSigningPageState
|
|||
bool _isSubmitting = false;
|
||||
bool _showSignaturePad = false;
|
||||
String? _errorMessage;
|
||||
bool _isKycRequired = false;
|
||||
int _downloadProgress = 0;
|
||||
int _downloadRetryCount = 0;
|
||||
|
||||
|
|
@ -90,10 +92,13 @@ class _PrePlantingMergeSigningPageState
|
|||
} catch (e) {
|
||||
debugPrint('[MergeSigningPage] PDF加载失败: $e');
|
||||
if (mounted) {
|
||||
final msg = e.toString();
|
||||
final isKyc = msg.contains('实名认证') || msg.contains('400');
|
||||
setState(() {
|
||||
_isPdfLoading = false;
|
||||
_downloadRetryCount++;
|
||||
_errorMessage = '加载合同失败,请点击重试';
|
||||
_isKycRequired = isKyc;
|
||||
_errorMessage = isKyc ? '请先完成实名认证方可查看和签署合同' : '加载合同失败,请点击重试';
|
||||
if (!isKyc) _downloadRetryCount++;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -306,8 +311,11 @@ class _PrePlantingMergeSigningPageState
|
|||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.cloud_download_outlined,
|
||||
color: Color(0xFFD4AF37), size: 56),
|
||||
Icon(
|
||||
_isKycRequired ? Icons.person_off_outlined : Icons.cloud_download_outlined,
|
||||
color: _isKycRequired ? Colors.red : const Color(0xFFD4AF37),
|
||||
size: 56,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
_errorMessage!,
|
||||
|
|
@ -315,17 +323,29 @@ class _PrePlantingMergeSigningPageState
|
|||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton.icon(
|
||||
onPressed: _loadPdf,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFD4AF37),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 32, vertical: 12)),
|
||||
icon: const Icon(Icons.refresh, color: Colors.white),
|
||||
label: const Text('重试',
|
||||
style: TextStyle(color: Colors.white, fontSize: 16)),
|
||||
),
|
||||
if (_downloadRetryCount > 0)
|
||||
if (_isKycRequired)
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => context.push(RoutePaths.kycEntry),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.red,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 32, vertical: 12)),
|
||||
icon: const Icon(Icons.verified_user, color: Colors.white),
|
||||
label: const Text('去完成实名认证',
|
||||
style: TextStyle(color: Colors.white, fontSize: 16)),
|
||||
)
|
||||
else
|
||||
ElevatedButton.icon(
|
||||
onPressed: _loadPdf,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFD4AF37),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 32, vertical: 12)),
|
||||
icon: const Icon(Icons.refresh, color: Colors.white),
|
||||
label: const Text('重试',
|
||||
style: TextStyle(color: Colors.white, fontSize: 16)),
|
||||
),
|
||||
if (!_isKycRequired && _downloadRetryCount > 0)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Text(
|
||||
|
|
|
|||
Loading…
Reference in New Issue