diff --git a/src/api/oa/erp/contractInfo/types.ts b/src/api/oa/erp/contractInfo/types.ts index 61e5674..3ca2f64 100644 --- a/src/api/oa/erp/contractInfo/types.ts +++ b/src/api/oa/erp/contractInfo/types.ts @@ -49,6 +49,31 @@ export interface ContractInfoVO { */ contractDate: string; + /** + * 合同属地标识(1中国大陆 2其他) + */ + contractTerritorialFlag?: string; + + /** + * 合同属地国家/地区(字典) + */ + contractTerritorialCountry?: string; + + /** + * 结算币种(CNY/USD/EUR) + */ + settlementCurrency?: string; + + /** + * 对人民币汇率 + */ + rmbExchangeRate?: number; + + /** + * 已生效客户订单标识(1是 0否) + */ + effectiveCustomerOrderFlag?: string; + /** * 合同总价 */ @@ -307,6 +332,31 @@ export interface ContractInfoForm extends BaseEntity { */ contractDate?: string; + /** + * 合同属地标识(1中国大陆 2其他) + */ + contractTerritorialFlag?: string; + + /** + * 合同属地国家/地区(字典) + */ + contractTerritorialCountry?: string; + + /** + * 结算币种(CNY/USD/EUR) + */ + settlementCurrency?: string; + + /** + * 对人民币汇率 + */ + rmbExchangeRate?: number; + + /** + * 已生效客户订单标识(1是 0否) + */ + effectiveCustomerOrderFlag?: string; + /** * 合同总价 */ @@ -563,6 +613,31 @@ export interface ContractInfoQuery extends PageQuery { */ contractDate?: string; + /** + * 合同属地标识(1中国大陆 2其他) + */ + contractTerritorialFlag?: string; + + /** + * 合同属地国家/地区(字典) + */ + contractTerritorialCountry?: string; + + /** + * 结算币种(CNY/USD/EUR) + */ + settlementCurrency?: string; + + /** + * 对人民币汇率 + */ + rmbExchangeRate?: number; + + /** + * 已生效客户订单标识(1是 0否) + */ + effectiveCustomerOrderFlag?: string; + /** * 合同总价 */ diff --git a/src/api/oa/erp/contractLedgerReport/index.ts b/src/api/oa/erp/contractLedgerReport/index.ts index a867bef..c3688e6 100644 --- a/src/api/oa/erp/contractLedgerReport/index.ts +++ b/src/api/oa/erp/contractLedgerReport/index.ts @@ -18,6 +18,9 @@ export interface ContractLedgerReportVO { externalContractCode: string; customerContractCode: string; contractDate: string; + contractTerritorialFlag: string; + contractTerritorialCountry: string; + settlementCurrency: string; orderContractCode: string; projectContractCode: string; customerName: string; diff --git a/src/views/oa/erp/contractInfo/edit.vue b/src/views/oa/erp/contractInfo/edit.vue index c24547e..d3e3f54 100644 --- a/src/views/oa/erp/contractInfo/edit.vue +++ b/src/views/oa/erp/contractInfo/edit.vue @@ -116,6 +116,46 @@ + + +
+ + {{ dict.label }} + + + + +
+
+
+ + + + + + + + - - +
+ +
+ +
+
+ + 已生效客户订单 + +
+ (无需盖章或签字,即刻生效的客户订单) +
+
+
@@ -400,7 +457,7 @@ @@ -723,7 +780,10 @@ const { contract_status, material_flag, contract_template_flag, - is_framework_contract + is_framework_contract, + contract_territorial_flag, + country_region, + currency_type } = toRefs( proxy?.useDict( 'contract_category', @@ -734,7 +794,10 @@ const { 'contract_status', 'material_flag', 'contract_template_flag', - 'is_framework_contract' + 'is_framework_contract', + 'contract_territorial_flag', + 'country_region', + 'currency_type' ) ); @@ -858,6 +921,7 @@ const materialDialog = reactive({ visible: false, title: '' }); +const editingMaterialIndex = ref(null); // 合同物料表单数据 const initMaterialFormData: ContractMaterialForm = { @@ -1011,6 +1075,11 @@ const initFormData: ContractInfoFormEx = { businessDirection: undefined, contractDeptId: undefined, contractDate: undefined, + contractTerritorialFlag: '1', + contractTerritorialCountry: undefined, + settlementCurrency: 'CNY', + rmbExchangeRate: 1, + effectiveCustomerOrderFlag: '0', totalPrice: 0, oneCustomerId: undefined, oneRepresent: undefined, @@ -1058,6 +1127,33 @@ const data = reactive<{ form: ContractInfoFormEx; rules: any }>({ contractName: [{ required: true, message: '合同名称不能为空', trigger: 'blur' }], businessDirection: [{ required: true, message: '业务方向不能为空', trigger: 'blur' }], contractManagerId: [{ required: true, message: '合同负责人不能为空', trigger: 'blur' }], + contractTerritorialFlag: [{ required: true, message: '合同属地标识不能为空', trigger: 'change' }], + contractTerritorialCountry: [ + { + validator: (_rule: any, _value: any, callback: (err?: Error) => void) => { + if (form.value.contractTerritorialFlag === '2' && !form.value.contractTerritorialCountry) { + callback(new Error('合同属地标识为“其他”时,国家/地区不能为空')); + return; + } + callback(); + }, + trigger: 'change' + } + ], + settlementCurrency: [{ required: true, message: '结算币种不能为空', trigger: 'change' }], + rmbExchangeRate: [{ required: true, message: '对人民币汇率不能为空', trigger: 'blur' }], + ossId: [ + { + validator: (_rule: any, _value: any, callback: (err?: Error) => void) => { + if (form.value.effectiveCustomerOrderFlag === '1' && !form.value.ossId) { + callback(new Error('已生效客户订单必须上传附件')); + return; + } + callback(); + }, + trigger: 'change' + } + ], contractTemplateFlag: [{ required: true, message: '合同模板标识不能为空', trigger: 'blur' }], isFrameworkContract: [{ required: true, message: '请选择关联框架合同', trigger: 'change' }], frameworkValidPeriod: [ @@ -1130,6 +1226,30 @@ watch( } ); +watch( + () => form.value.contractTerritorialFlag, + (newVal) => { + // 合同属地标识为“其他”时,新增物料默认税率为0 + initMaterialFormData.taxRate = newVal === '2' ? 0 : 13; + if (newVal === '2') { + materialForm.value.taxRate = 0; + } else { + form.value.contractTerritorialCountry = undefined; + } + }, + { immediate: true } +); + +watch( + () => form.value.settlementCurrency, + (newVal) => { + if (newVal === 'CNY') { + form.value.rmbExchangeRate = 1 as any; + } + }, + { immediate: true } +); + // 生成合同编号 const generateContractCode = async () => { if (isCodeGenerated.value) return; // 如果已经生成过,直接返回 @@ -1292,14 +1412,16 @@ const submitOss = () => { // 新增物料(新增合同时也可添加,不依赖contractId) const handleAddMaterial = () => { resetMaterialForm(); + editingMaterialIndex.value = null; materialForm.value.contractId = form.value.contractId; materialDialog.visible = true; materialDialog.title = '新增合同物料'; }; // 编辑物料 -const handleEditMaterial = (row: ContractMaterialVO) => { +const handleEditMaterial = (row: ContractMaterialVO, rowIndex: number) => { resetMaterialForm(); + editingMaterialIndex.value = rowIndex; materialForm.value = { ...row }; materialDialog.visible = true; materialDialog.title = '编辑合同物料'; @@ -1333,11 +1455,14 @@ const handleDeleteMaterial = async (row: ContractMaterialVO) => { const resetMaterialForm = () => { materialForm.value = { ...initMaterialFormData }; materialFormRef.value?.resetFields(); + // 合同属地标识=2 物料税率默认0 + materialForm.value.taxRate = form.value.contractTerritorialFlag === '2' ? 0 : 13; }; // 取消物料编辑 const cancelMaterial = () => { resetMaterialForm(); + editingMaterialIndex.value = null; materialDialog.visible = false; }; @@ -1490,7 +1615,11 @@ const submitMaterialForm = () => { unitName: unitName }; - if (materialForm.value.contractMaterialId) { + const editIndex = editingMaterialIndex.value; + if (editIndex !== null && editIndex >= 0 && editIndex < (form.value as any).contractMaterialList.length) { + // 优先按行索引回写,兼容框架合同带出但无主键ID的物料 + (form.value as any).contractMaterialList[editIndex] = materialData; + } else if (materialForm.value.contractMaterialId) { // 编辑模式:更新现有物料 const index = (form.value as any).contractMaterialList.findIndex( (item: any) => item.contractMaterialId === materialForm.value.contractMaterialId @@ -1511,6 +1640,7 @@ const submitMaterialForm = () => { calculateTotalPrice(); proxy?.$modal.msgSuccess('操作成功'); + editingMaterialIndex.value = null; materialDialog.visible = false; } }); diff --git a/src/views/oa/erp/contractInfo/index.vue b/src/views/oa/erp/contractInfo/index.vue index d9af35f..ea7fe2e 100644 --- a/src/views/oa/erp/contractInfo/index.vue +++ b/src/views/oa/erp/contractInfo/index.vue @@ -195,6 +195,22 @@ {{ parseTime(scope.row.frameworkValidPeriod, '{y}-{m}-{d}') }} + + + + + + + + + +