jianghaiqing 3 weeks ago
commit 34754ac63c

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DS.Module.Core.Enums
{
/// <summary>
/// 组织机构授权类型枚举
/// </summary>
public enum OrgAuthTypeEnum
{
/// <summary>
/// 进项发票请求密钥
/// </summary>
[Description("InInvoice")]
InInvoice = 1,
/// <summary>
/// 银行流水请求密钥
/// </summary>
[Description("BankStatement")]
BankStatement = 2,
/// <summary>
/// 钉钉请求密钥
/// </summary>
[Description("DingConfig")]
DingConfig = 3,
/// <summary>
/// 钉钉报销审批模板编号
/// </summary>
[Description("DingProcessCode")]
DingProcessCode = 4,
}
}

@ -385,7 +385,7 @@ namespace DS.Module.Core
/// <summary>
/// 客户干系人争议驳回
/// </summary>
[Description("客户干系人争议处理")]
[Description("客户干系人争议驳回")]
CLIENT_STAKEHOLDER_DISPUTE_REJECTED = -503,
/// <summary>
/// 费用审核驳回
@ -535,9 +535,9 @@ namespace DS.Module.Core
ReimbursementApproval =1101,
/// <summary>
/// 报销单审核
/// 报销单驳回
/// </summary>
[Description("报销单审核")]
[Description("报销单驳回")]
Reimbursement_REJECTED = -1101
#endregion

@ -0,0 +1,476 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace DS.Module.Core.Helpers
{
#region
/**
*
*/
public class DingTalkEncryptor
{
//private static readonly Charset CHARSET = Charset.forName("utf-8");
//private static readonly Base64 base64 = new Base64();
private byte[] aesKey;
private String token;
private String corpId;
/**ask getPaddingBytes key固定长度**/
private static readonly int AES_ENCODE_KEY_LENGTH = 43;
/**加密随机字符串字节长度**/
private static readonly int RANDOM_LENGTH = 16;
/**
*
* @param token token
* @param encodingAesKey EncodingAESKey
* @param corpId -, 使appKey
* -, 使corpId
* , 使suiteKey
*
* @throws DingTalkEncryptException
*/
public DingTalkEncryptor(String token, String encodingAesKey, String corpId)
{
if (null == encodingAesKey || encodingAesKey.Length != AES_ENCODE_KEY_LENGTH)
{
throw new DingTalkEncryptException(DingTalkEncryptException.AES_KEY_ILLEGAL);
}
this.token = token;
this.corpId = corpId;
aesKey = Convert.FromBase64String(encodingAesKey + "=");
}
/**
* ,Map
*/
public Dictionary<String, String> getEncryptedMap(String plaintext)
{
var time = DateTime.Now.Millisecond;
return getEncryptedMap(plaintext, time);
}
/**
* ,Map
* @param plaintext
* @param timeStamp
* @param nonce
* @return
* @throws DingTalkEncryptException
*/
public Dictionary<String, String> getEncryptedMap(String plaintext, long timeStamp)
{
if (null == plaintext)
{
throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_PLAINTEXT_ILLEGAL);
}
var nonce = Utils.getRandomStr(RANDOM_LENGTH);
if (null == nonce)
{
throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_NONCE_ILLEGAL);
}
String encrypt = this.encrypt(nonce, plaintext);
String signature = getSignature(token, timeStamp.ToString(), nonce, encrypt);
Dictionary<String, String> resultMap = new Dictionary<String, String>();
resultMap["msg_signature"] = signature;
resultMap["encrypt"] = encrypt;
resultMap["timeStamp"] = timeStamp.ToString();
resultMap["nonce"] = nonce;
return resultMap;
}
/**
*
* @param msgSignature
* @param timeStamp
* @param nonce
* @param encryptMsg
* @return
* @throws DingTalkEncryptException
*/
public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg)
{
//校验签名
String signature = getSignature(token, timeStamp, nonce, encryptMsg);
if (!signature.Equals(msgSignature))
{
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
}
// 解密
String result = decrypt(encryptMsg);
return result;
}
/*
* .
* @param text
* @return base64
*/
private String encrypt(String random, String plaintext)
{
try
{
byte[] randomBytes = System.Text.Encoding.UTF8.GetBytes(random);// random.getBytes(CHARSET);
byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plaintext);// plaintext.getBytes(CHARSET);
byte[] lengthByte = Utils.int2Bytes(plainTextBytes.Length);
byte[] corpidBytes = System.Text.Encoding.UTF8.GetBytes(corpId);// corpId.getBytes(CHARSET);
//MemoryStream byteStream = new MemoryStream();
var bytestmp = new List<byte>();
bytestmp.AddRange(randomBytes);
bytestmp.AddRange(lengthByte);
bytestmp.AddRange(plainTextBytes);
bytestmp.AddRange(corpidBytes);
byte[] padBytes = PKCS7Padding.getPaddingBytes(bytestmp.Count);
bytestmp.AddRange(padBytes);
byte[] unencrypted = bytestmp.ToArray();
RijndaelManaged rDel = new RijndaelManaged();
rDel.Mode = CipherMode.CBC;
rDel.Padding = PaddingMode.Zeros;
rDel.Key = aesKey;
rDel.IV = aesKey.ToList().Take(16).ToArray();
ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(unencrypted, 0, unencrypted.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
//Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
//SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
//IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
//cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
//byte[] encrypted = cipher.doFinal(unencrypted);
//String result = base64.encodeToString(encrypted);
//return result;
}
catch (Exception e)
{
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_ENCRYPT_TEXT_ERROR);
}
}
/*
* .
* @param text
* @return
*/
private String decrypt(String text)
{
byte[] originalArr;
try
{
byte[] toEncryptArray = Convert.FromBase64String(text);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Mode = CipherMode.CBC;
rDel.Padding = PaddingMode.Zeros;
rDel.Key = aesKey;
rDel.IV = aesKey.ToList().Take(16).ToArray();
ICryptoTransform cTransform = rDel.CreateDecryptor();
originalArr = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
//return System.Text.UTF8Encoding.UTF8.GetString(resultArray);
//设置解密模式为AES的CBC模式
//Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
//SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
//IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
//cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
//使用BASE64对密文进行解码
//byte[] encrypted = Base64.decodeBase64(text);
//解密
//originalArr = cipher.doFinal(encrypted);
}
catch (Exception e)
{
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_ERROR);
}
String plainText;
String fromCorpid;
try
{
// 去除补位字符
byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);
Console.Out.WriteLine("bytes size:" + bytes.Length);
// 分离16位随机字符串,网络字节序和corpId
byte[] networkOrder = bytes.Skip(16).Take(4).ToArray();// Arrays.copyOfRange(bytes, 16, 20);
for (int i = 0; i < 4; i++)
{
Console.Out.WriteLine("networkOrder size:" + (int)networkOrder[i]);
}
// Console.Out.WriteLine("bytes plainText:" + networkOrder.Length + " " + JsonSerializer.Serialize(networkOrder));
int plainTextLegth = Utils.bytes2int(networkOrder);
Console.Out.WriteLine("bytes size:" + plainTextLegth);
plainText = System.Text.UTF8Encoding.UTF8.GetString(bytes.Skip(20).Take(plainTextLegth).ToArray()); // new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET);
fromCorpid = System.Text.UTF8Encoding.UTF8.GetString(bytes.Skip(20 + plainTextLegth).ToArray()); //new String(Arrays.copyOfRange(bytes, 20 + plainTextLegth, bytes.length), CHARSET);
Console.Out.WriteLine("bytes plainText:" + plainText);
}
catch (Exception e)
{
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_LENGTH_ERROR);
}
Console.Out.WriteLine(fromCorpid + "=====" + corpId);
// corpid不相同的情况
if (!fromCorpid.Equals(corpId))
{
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_CORPID_ERROR);
}
return plainText;
}
/**
*
* @param token isv token
* @param timestamp
* @param nonce
* @param encrypt
* @return
* @throws DingTalkEncryptException
*/
public String getSignature(String token, String timestamp, String nonce, String encrypt)
{
try
{
Console.Out.WriteLine(encrypt);
String[] array = new String[] { token, timestamp, nonce, encrypt };
System.Array.Sort(array, StringComparer.Ordinal);
//var tmparray = array.ToList();
//tmparray.Sort(new JavaStringComper());
//array = tmparray.ToArray();
// Console.Out.WriteLine("array:" + JsonSerializer.Serialize(array));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++)
{
sb.Append(array[i]);
}
String str = sb.ToString();
Console.Out.WriteLine(str);
//MessageDigest md = MessageDigest.getInstance("SHA-1");
//md.update(str.getBytes());
//byte[] digest = md.digest();
System.Security.Cryptography.SHA1 hash = System.Security.Cryptography.SHA1.Create();
System.Text.Encoding encoder = System.Text.Encoding.ASCII;
byte[] combined = encoder.GetBytes(str);
// byte 转换
//sbyte[] myByte = new sbyte[]
//byte[] mySByte = new byte[myByte.Length];
//for (int i = 0; i < myByte.Length; i++)
//{
// if (myByte[i] > 127)
// mySByte[i] = (sbyte)(myByte[i] - 256);
// else
// mySByte[i] = (sbyte)myByte[i];
//}
byte[] digest = hash.ComputeHash(combined);
StringBuilder hexstr = new StringBuilder();
String shaHex = "";
for (int i = 0; i < digest.Length; i++)
{
shaHex = ((int)digest[i]).ToString("x");// Integer.toHexString(digest[i] & 0xFF);
if (shaHex.Length < 2)
{
hexstr.Append(0);
}
hexstr.Append(shaHex);
}
return hexstr.ToString();
}
catch (Exception e)
{
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
}
}
}
/**
*
*/
public class DingTalkEncryptException : Exception
{
/**成功**/
public static readonly int SUCCESS = 0;
/**加密明文文本非法**/
public readonly static int ENCRYPTION_PLAINTEXT_ILLEGAL = 900001;
/**加密时间戳参数非法**/
public readonly static int ENCRYPTION_TIMESTAMP_ILLEGAL = 900002;
/**加密随机字符串参数非法**/
public readonly static int ENCRYPTION_NONCE_ILLEGAL = 900003;
/**不合法的aeskey**/
public readonly static int AES_KEY_ILLEGAL = 900004;
/**签名不匹配**/
public readonly static int SIGNATURE_NOT_MATCH = 900005;
/**计算签名错误**/
public readonly static int COMPUTE_SIGNATURE_ERROR = 900006;
/**计算加密文字错误**/
public readonly static int COMPUTE_ENCRYPT_TEXT_ERROR = 900007;
/**计算解密文字错误**/
public readonly static int COMPUTE_DECRYPT_TEXT_ERROR = 900008;
/**计算解密文字长度不匹配**/
public readonly static int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR = 900009;
/**计算解密文字corpid不匹配**/
public readonly static int COMPUTE_DECRYPT_TEXT_CORPID_ERROR = 900010;
private static Dictionary<int, String> msgMap = new Dictionary<int, String>();
static DingTalkEncryptException()
{
msgMap[SUCCESS] = "成功";
msgMap[ENCRYPTION_PLAINTEXT_ILLEGAL] = "加密明文文本非法";
msgMap[ENCRYPTION_TIMESTAMP_ILLEGAL] = "加密时间戳参数非法";
msgMap[ENCRYPTION_NONCE_ILLEGAL] = "加密随机字符串参数非法";
msgMap[SIGNATURE_NOT_MATCH] = "签名不匹配";
msgMap[COMPUTE_SIGNATURE_ERROR] = "签名计算失败";
msgMap[AES_KEY_ILLEGAL] = "不合法的aes key";
msgMap[COMPUTE_ENCRYPT_TEXT_ERROR] = "计算加密文字错误";
msgMap[COMPUTE_DECRYPT_TEXT_ERROR] = "计算解密文字错误";
msgMap[COMPUTE_DECRYPT_TEXT_LENGTH_ERROR] = "计算解密文字长度不匹配";
msgMap[COMPUTE_DECRYPT_TEXT_CORPID_ERROR] = "计算解密文字corpid不匹配";
}
private int code;
public DingTalkEncryptException(int exceptionCode) : base(msgMap[exceptionCode])
{
this.code = exceptionCode;
}
}
/*
* PKCS7
*/
public class PKCS7Padding
{
//private readonly static Charset CHARSET = Charset.forName("utf-8");
private readonly static int BLOCK_SIZE = 32;
/**
* mode
* @param count
* @return
*/
public static byte[] getPaddingBytes(int count)
{
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
if (amountToPad == 0)
{
amountToPad = BLOCK_SIZE;
}
char padChr = chr(amountToPad);
String tmp = string.Empty; ;
for (int index = 0; index < amountToPad; index++)
{
tmp += padChr;
}
return System.Text.Encoding.UTF8.GetBytes(tmp);
}
/**
* mode
* @param decrypted
* @return
*/
public static byte[] removePaddingBytes(byte[] decrypted)
{
int pad = (int)decrypted[decrypted.Length - 1];
if (pad < 1 || pad > BLOCK_SIZE)
{
pad = 0;
}
//Array.Copy()
var output = new byte[decrypted.Length - pad];
System.Array.Copy(decrypted, output, decrypted.Length - pad);
return output;
}
private static char chr(int a)
{
byte target = (byte)(a & 0xFF);
return (char)target;
}
}
/**
*
*/
public class Utils
{
/**
*
* @return
*/
public static String getRandomStr(int count)
{
String baset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++)
{
int number = random.Next(baset.Length);
sb.Append(baset[number]);
}
return sb.ToString();
}
/*
* intbyte,
*/
public static byte[] int2Bytes(int count)
{
byte[] byteArr = new byte[4];
byteArr[3] = (byte)(count & 0xFF);
byteArr[2] = (byte)(count >> 8 & 0xFF);
byteArr[1] = (byte)(count >> 16 & 0xFF);
byteArr[0] = (byte)(count >> 24 & 0xFF);
return byteArr;
}
/**
* bytesint
* @param byteArr
* @return
*/
public static int bytes2int(byte[] byteArr)
{
int count = 0;
for (int i = 0; i < 4; ++i)
{
count <<= 8;
count |= byteArr[i] & 255;
}
return count;
}
}
public class JavaStringComper : IComparer<string>
{
public int Compare(string x, string y)
{
return String.Compare(x, y);
}
}
#endregion
}

@ -63,4 +63,18 @@ namespace DS.WMS.Core.Fee.Dtos
public bool AuditOnly { get; set; }
}
public class ReimbursementRevokedInput
{
public long Id { get; set; }
}
public class ReimbursementAuditRequest: AuditRequest
{
/// <summary>
/// 会计科目
/// </summary>
public string LedgerAccount { get; set; }
}
}

@ -81,6 +81,11 @@ namespace DS.WMS.Core.Fee.Dtos
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 报销事由
/// </summary>
public string Reason { get; set; }
}
@ -106,6 +111,12 @@ namespace DS.WMS.Core.Fee.Dtos
/// </summary>
public string PayeeName { get; set; }
/// <summary>
/// 事由
/// </summary>
public string Reason { get; set; }
public List<ReimbursementReqData> Data { get; set; }
}

@ -76,5 +76,16 @@ namespace DS.WMS.Core.Fee.Entity
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 报销事由
/// </summary>
public string Reason { get; set; }
/// <summary>
/// 会计科目
/// </summary>
public string LedgerAccount { get; set; }
}
}

@ -45,7 +45,7 @@ namespace DS.WMS.Core.Fee.Interface
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task< DataResult> ReimbursementRevoked(string id);
Task< DataResult> ReimbursementRevoked(long id);
/// <summary>
/// 根据审批结果更新审批状态
@ -67,7 +67,7 @@ namespace DS.WMS.Core.Fee.Interface
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<DataResult> AuditAsync(AuditRequest request);
Task<DataResult> AuditAsync(ReimbursementAuditRequest request);
}
}

@ -0,0 +1,355 @@
using AlibabaCloud.SDK.Dingtalkworkflow_1_0.Models;
using DS.Module.SqlSugar;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Invoice.Dtos;
using DS.WMS.Core.Sys.Interface;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tea;
namespace DS.WMS.Core.Fee.Method
{
public class DingDing
{
/// <summary>
/// 获取token
/// </summary>
public static string GetDingToken(string Key, string Secret)
{
AlibabaCloud.SDK.Dingtalkoauth2_1_0.Client client = CreateClient1();
AlibabaCloud.SDK.Dingtalkoauth2_1_0.Models.GetAccessTokenRequest getAccessTokenRequest = new AlibabaCloud.SDK.Dingtalkoauth2_1_0.Models.GetAccessTokenRequest
{
AppKey = Key, //"dingplilbecwnldzcdwc",
AppSecret = Secret //"V1jtywZwJNtcTw9PfY5am2nsqacgserqNVOx-_yHsv-5YIypKKG2R0Qm19lpnHCj",
};
try
{
var p = client.GetAccessToken(getAccessTokenRequest);
return p.Body.AccessToken;
}
catch (TeaException err)
{
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
catch (Exception _err)
{
TeaException err = new TeaException(new Dictionary<string, object>
{
{ "message", _err.Message }
});
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
return "";
}
/// <summary>
/// 更新表单
/// </summary>
/// <param name="token">钉钉token</param>
/// <param name="ProcessCode">审批模板Id</param>
/// <param name="TenantId">租户Id</param>
public static void UpDingOAForm(string token, string ProcessCode, List<InInvoice> inInvoicesData)
{
AlibabaCloud.SDK.Dingtalkworkflow_1_0.Client client = CreateClient();
FormCreateHeaders formCreateHeaders = new FormCreateHeaders();
formCreateHeaders.XAcsDingtalkAccessToken = token;
#region 费用类别
FormComponent fylx = new FormComponent
{
ComponentType = "DDSelectField",
Props = new FormComponentProps
{
ComponentId = "DDSelectField-fylx", // 控件id表单内唯一与bizAlias二选一
Required = true, // 控件是否必填
Label = "费用类别", // 控件标题
Placeholder = "请选择", // 输入提示
Print = "1",//是否参与打印
Disabled = false, //是否可编辑
Options = new List<SelectOption> {
new SelectOption{Value = "项目费用",Key = "1"},
new SelectOption { Value = "部门费用", Key = "2" },
new SelectOption { Value = "差旅费用", Key = "3" },
new SelectOption { Value = "其他", Key = "4" }
}
}
};
#endregion
#region 项目名称
FormComponent xmmc = new FormComponent
{
ComponentType = "TextField",
Props = new FormComponentProps
{
ComponentId = "TextField-abcd", // 控件id表单内唯一与bizAlias二选一
Required = true, // 控件是否必填
Label = "项目名称", // 控件标题
Placeholder = "请输入",// 输入提示
Print = "1",//是否参与打印
Disabled = false, //是否可编辑
}
};
#endregion
#region 费用明细
var taxinfo = inInvoicesData;
List<SelectOption> selectOptions = new List<SelectOption>();
foreach (var item in taxinfo)
{
SelectOption st = new SelectOption();
st.Value = ($"金额:{item.Amount};销方名称:{item.SellerName};发票号码:{item.InvoiceNumber}");
st.Key = item.InvoiceNumber;
selectOptions.Add(st);
}
FormComponent fymx = new FormComponent
{
ComponentType = "DDSelectField",
Props = new FormComponentProps
{
ComponentId = "DDSelectField-fymx", // 控件id表单内唯一与bizAlias二选一
Required = false, // 控件是否必填
Label = "费用明细", // 控件标题
Placeholder = "请选择", // 输入提示
Print = "1",//是否参与打印
Disabled = false, //是否可编辑
Options = selectOptions
}
};
#endregion
#region 金额
FormComponent xmmcA = new FormComponent
{
ComponentType = "MoneyField",
Props = new FormComponentProps
{
ComponentId = "MoneyField_1JZJIQ", // 控件id表单内唯一与bizAlias二选一
Required = true, // 控件是否必填
Label = "金额(元)", // 控件标题
Placeholder = "请输入金额",// 输入提示
Print = "1",//是否参与打印
Disabled = false, //是否可编辑
}
};
#endregion
#region 收款账户
FormComponent skzh = new FormComponent
{
ComponentType = "RecipientAccountField",
Props = new FormComponentProps
{
ComponentId = "RecipientAccountField_7KZ7T", // 控件id表单内唯一与bizAlias二选一
Required = true, // 控件是否必填
Label = "收款账户", // 控件标题
Placeholder = "请选择",// 输入提示
Disabled = false,
}
};
#endregion
#region 关联审批单
FormComponent glspd = new FormComponent
{
ComponentType = "RelateField",
Props = new FormComponentProps
{
ComponentId = "RelateField_7KZ7T", // 控件id表单内唯一与bizAlias二选一
Required = false, // 控件是否必填
Label = "关联审批单", // 控件标题
Placeholder = "请选择",// 输入提示
Disabled = false,
}
};
#endregion
FormCreateRequest formCreateRequest = new FormCreateRequest
{
ProcessCode = ProcessCode,// "PROC-528BFFFF-00D1-4AF0-AB5F-7BFB89787994",
Name = "测试费用报销(电子发票)",
Description = "测试费用报销使用",
FormComponents = new List<FormComponent>
{
fylx,//费用类别
xmmc,//项目名称
fymx,//费用明细
xmmcA,//金额
skzh,//收款账户
glspd //关联审批单
},
};
try
{
client.FormCreateWithOptions(formCreateRequest, formCreateHeaders, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
}
catch (TeaException err)
{
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
catch (Exception _err)
{
TeaException err = new TeaException(new Dictionary<string, object>
{
{ "message", _err.Message }
});
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
/**
* 使 Token Client
* @return Client
* @throws Exception
*/
public static AlibabaCloud.SDK.Dingtalkoauth2_1_0.Client CreateClient1()
{
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config();
config.Protocol = "https";
config.RegionId = "central";
return new AlibabaCloud.SDK.Dingtalkoauth2_1_0.Client(config);
}
public static AlibabaCloud.SDK.Dingtalkworkflow_1_0.Client CreateClient()
{
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config();
config.Protocol = "https";
config.RegionId = "central";
return new AlibabaCloud.SDK.Dingtalkworkflow_1_0.Client(config);
}
/// <summary>
/// 获取审批实例详情
/// </summary>
/// <param name="ProcessInstanceId">审批实例Id</param>
/// <param name="Token">钉钉token</param>
/// <returns></returns>
public static GetProcessInstanceResponse GetProcessInstanceWithOptions(string ProcessInstanceId, string Token)
{
AlibabaCloud.SDK.Dingtalkworkflow_1_0.Client client = CreateClient();
AlibabaCloud.SDK.Dingtalkworkflow_1_0.Models.GetProcessInstanceHeaders getProcessInstanceHeaders = new AlibabaCloud.SDK.Dingtalkworkflow_1_0.Models.GetProcessInstanceHeaders();
getProcessInstanceHeaders.XAcsDingtalkAccessToken = Token;
AlibabaCloud.SDK.Dingtalkworkflow_1_0.Models.GetProcessInstanceRequest getProcessInstanceRequest = new AlibabaCloud.SDK.Dingtalkworkflow_1_0.Models.GetProcessInstanceRequest
{
ProcessInstanceId = ProcessInstanceId,
};
try
{
return client.GetProcessInstanceWithOptions(getProcessInstanceRequest, getProcessInstanceHeaders, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
}
catch (TeaException err)
{
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
catch (Exception _err)
{
TeaException err = new TeaException(new Dictionary<string, object>
{
{ "message", _err.Message }
});
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
return new GetProcessInstanceResponse();
}
/// <summary>
/// 获取钉钉报销审批列表
/// </summary>
/// <param name="token">钉钉token</param>
/// <param name="ProcessCode">钉钉模板Id</param>
/// <param name="StartTime">开始时间</param>
/// <param name="EndTime">结束时间</param>
/// <param name="Data">获取到的数据集</param>
/// <param name="NextToken">分页游标</param>
/// <returns></returns>
public static List<string> GetProcessList(string token, string ProcessCode, long StartTime, long EndTime, List<string> Data, int NextToken = 0)
{
AlibabaCloud.SDK.Dingtalkworkflow_1_0.Client client = CreateClient();
ListProcessInstanceIdsHeaders listProcessInstanceIdsHeaders = new ListProcessInstanceIdsHeaders();
listProcessInstanceIdsHeaders.XAcsDingtalkAccessToken = token;
ListProcessInstanceIdsRequest listProcessInstanceIdsRequest = new ListProcessInstanceIdsRequest
{
ProcessCode = ProcessCode,
StartTime = StartTime,
EndTime = EndTime,
NextToken = NextToken,
MaxResults = 20
};
try
{
var data = client.ListProcessInstanceIdsWithOptions(listProcessInstanceIdsRequest, listProcessInstanceIdsHeaders, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
foreach (var item in data.Body.Result.List)
{
Data.Add(item);
}
if (data.Body.Result.NextToken != null)
{
GetProcessList(token, ProcessCode, StartTime, EndTime, Data, Convert.ToInt32(data.Body.Result.NextToken));
}
return Data;
}
catch (TeaException err)
{
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
catch (Exception _err)
{
TeaException err = new TeaException(new Dictionary<string, object>
{
{ "message", _err.Message }
});
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
return new List<string>();
}
}
}

@ -1,4 +1,5 @@
using DS.Module.Core;
using AngleSharp.Dom;
using DS.Module.Core;
using DS.Module.Core.Enums;
using DS.Module.Core.Extensions;
using DS.Module.SqlSugar;
@ -8,6 +9,7 @@ using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Fee.Interface;
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.Flow.Interface;
using DS.WMS.Core.Sys.Entity;
using DS.WMS.Core.Sys.Interface;
using DS.WMS.Core.Sys.Method;
using DS.WMS.Core.TaskInteraction.Dtos;
@ -72,7 +74,7 @@ namespace DS.WMS.Core.Fee.Method
return data;
}
/// <summary>
/// 提交报销申请
/// 新增报销申请
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
@ -123,7 +125,7 @@ namespace DS.WMS.Core.Fee.Method
return DataResult.Failed($"发票号{item.InvoiceNumber}不存在,请检查");
}
//发票报销状态 校验 待完善
//发票报销状态 校验
if (inviceinfo.ReimbursementType == ReimbursementTypeEnums.UnderReview) //报销中
{
return DataResult.Failed($"提交失败,发票号{item.InvoiceNumber}正在报销,请检查");
@ -132,9 +134,8 @@ namespace DS.WMS.Core.Fee.Method
{
return DataResult.Failed($"提交失败,发票号{item.InvoiceNumber}已报销,请检查");
}
inviceinfo.ReimbursementType = ReimbursementTypeEnums.NotSubmitted;
inviceinfo.ReimbursementType = ReimbursementTypeEnums.UnderReview;
tenantDb.Updateable(inviceinfo).ExecuteCommand();
var dataDetail = item.Adapt<FeeReimbursementDetail>();
@ -169,7 +170,7 @@ namespace DS.WMS.Core.Fee.Method
{
return DataResult.Failed($"提交失败,发票号{item.InvoiceNumber}已报销,请检查");
}
}
#endregion
@ -194,9 +195,15 @@ namespace DS.WMS.Core.Fee.Method
dataDetail.PId = info.Id;
dataDetail.Amount = (decimal)inviceinfo.Amount;
tenantDb.Insertable(dataDetail).ExecuteReturnEntity();
inviceinfo.ReimbursementType = ReimbursementTypeEnums.UnderReview;
tenantDb.Updateable(inviceinfo).ExecuteCommand();
}
return DataResult.Successed("添加成功!", info.Id, MultiLanguageConst.DataCreateSuccess);
}
return await Task.FromResult(DataResult.Successed("操作成功"));
}
@ -231,15 +238,15 @@ namespace DS.WMS.Core.Fee.Method
return DataResult.Failed($"发票号{item.InvoiceNumber}不存在,请检查");
}
//发票报销状态 校验 待完善
if (inviceinfo.ReimbursementType == ReimbursementTypeEnums.UnderReview) //报销中
{
return DataResult.Failed($"提交失败,发票号{item.InvoiceNumber}正在报销,请检查");
}
if (inviceinfo.ReimbursementType == ReimbursementTypeEnums.Approved) //已报销
{
return DataResult.Failed($"提交失败,发票号{item.InvoiceNumber}已报销,请检查");
}
////发票报销状态 校验 待完善
//if (inviceinfo.ReimbursementType == ReimbursementTypeEnums.UnderReview) //报销中
//{
// return DataResult.Failed($"提交失败,发票号{item.InvoiceNumber}正在报销,请检查");
//}
//if (inviceinfo.ReimbursementType == ReimbursementTypeEnums.Approved) //已报销
//{
// return DataResult.Failed($"提交失败,发票号{item.InvoiceNumber}已报销,请检查");
//}
}
#endregion
@ -279,9 +286,7 @@ namespace DS.WMS.Core.Fee.Method
{
return await Task.FromResult(DataResult.Successed(result.Message));
}
#endregion
}
/// <summary>
@ -298,21 +303,24 @@ namespace DS.WMS.Core.Fee.Method
.First();
var dtlist= tenantDb.Queryable<FeeReimbursementDetail>().Where(t => t.PId == data.Id).ToList();
data.Data = new List<GetReimbursementResData>();
foreach (var item in dtlist)
{
var dt= tenantDb.Queryable<InInvoice>().Where(t => t.InvoiceNumber == item.InvoiceNumber).Select<GetReimbursementResData>().First();
if (dt != null)
{
data.Data = new List<GetReimbursementResData>();
data.Data.Add(dt);
foreach (var itemdata in data.Data)
{
itemdata.Data = new List<InInvoiceDetail>();
itemdata.Data = tenantDb.Queryable<InInvoiceDetail>().Where(t => t.InvoiceNumber == item.InvoiceNumber).ToList();
}
}
}
foreach (var itemdata in data.Data)
{
itemdata.Data = new List<InInvoiceDetail>();
itemdata.Data = tenantDb.Queryable<InInvoiceDetail>().Where(t => t.InvoiceNumber == itemdata.InvoiceNumber).ToList();
}
return DataResult<GetReimbursementRes>.Success(data, MultiLanguageConst.DataQuerySuccess);
}
@ -322,51 +330,85 @@ namespace DS.WMS.Core.Fee.Method
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<DataResult> ReimbursementRevoked(string id)
public async Task<DataResult> ReimbursementRevoked(long id)
{
//查询当前报销单
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var data = tenantDb.Queryable<FeeReimbursement>()
.Where(a => a.Id == long.Parse(id))
.Where(a => a.Id == id)
.Select<FeeReimbursement>()
.First();
if (data.ReimbursementType != ReimbursementTypeEnums.NotSubmitted)
if (data.ReimbursementType == ReimbursementTypeEnums.Approved)
{
return DataResult.Failed("报销单审批已通过,不可撤回!");
}
if (data.ReimbursementType == ReimbursementTypeEnums.Rejected)
{
return DataResult.Failed("报销单已审批,不可撤回!");
}
if (data.ReimbursementType == ReimbursementTypeEnums.Revoked)
{
return DataResult.Failed("报销单只有未审批可撤回!");
return DataResult.Failed("报销单已撤销,不可重复撤回!");
}
data.ReimbursementType = ReimbursementTypeEnums.Revoked;
db.Updateable(data).ExecuteCommand();
tenantDb.Updateable(data).ExecuteCommand();
var dataDetail = tenantDb.Queryable<FeeReimbursementDetail>()
.Where(a => a.PId == long.Parse(id))
.Select<FeeReimbursement>()
.Where(a => a.PId == id)
.ToList();
foreach (var item in dataDetail)
{
item.ReimbursementType = ReimbursementTypeEnums.Revoked;
db.Updateable(item).ExecuteCommand();
item.Status = ReimbursementTypeEnums.Revoked;
tenantDb.Updateable(item).ExecuteCommand();
var inviceinfo = tenantDb.Queryable<InInvoice>().Where(t => t.InvoiceNumber == item.InvoiceNumber).First();
inviceinfo.ReimbursementType = ReimbursementTypeEnums.NotSubmitted; //审核撤销,将对应的报销发票设为未审核状态
tenantDb.Updateable(inviceinfo).ExecuteCommand();
}
//撤销审批任务
var tsreq = new TaskRequest
if (data.ReimbursementType == ReimbursementTypeEnums.UnderReview)
{
BusinessId = data.Id,
TaskTypeName = TaskBaseTypeEnum.ReimbursementApproval.ToString(),
};
#region 撤销钉钉审批任务
#endregion
#region 撤销东胜8工作流的审批任务
//撤销审批任务
var tsreq = new TaskRequest
{
BusinessId = data.Id,
TaskTypeName = TaskBaseTypeEnum.ReimbursementApproval.ToString(),
};
var result = await taskService.WithdrawAsync(tsreq);
if (!result.Succeeded)
{
return await Task.FromResult(DataResult.Failed(result.Message));
}
else
{
return await Task.FromResult(DataResult.Successed(result.Message));
}
#endregion
var result = await taskService.WithdrawAsync(tsreq);
if (!result.Succeeded)
{
return await Task.FromResult(DataResult.Failed(result.Message));
}
else
{
return await Task.FromResult(DataResult.Successed(result.Message));
}
return await Task.FromResult(DataResult.Successed("操作成功"));
}
/// <summary>
@ -434,8 +476,31 @@ namespace DS.WMS.Core.Fee.Method
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult> AuditAsync(AuditRequest request)
public async Task<DataResult> AuditAsync(ReimbursementAuditRequest request)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var info = await tenantDb.Queryable<FeeReimbursement>().Where(x =>request.Ids.Contains( x.Id)).ToListAsync();
if (info.IsNull())
return await Task.FromResult(DataResult.Failed("不存在的报销单信息!"));
//修改会计科目
foreach (var item in info)
{
item.LedgerAccount = request.LedgerAccount;
}
db.Updateable(info).ExecuteCommand();
//获取当前审批人信息
var userinfo= db.Queryable<SysUser>().Where(t => t.Id.ToString()== user.UserId).First();
if (!string.IsNullOrWhiteSpace( userinfo.DingUserId))
{
//TODO 窦汉东 同步钉钉当前审批人的审批状态
}
if (await taskService2.Value.HasAuthorizedAsync())
{
return await taskService2.Value.AuditAsync(new TaskAuditRequest

@ -39,7 +39,7 @@ namespace DS.WMS.Core.QuarztJobs.Method
return;
}
var orgauthlist = db.Queryable<SysOrgAuth>().ClearFilter().Where(t => t.Deleted == false && t.Type == "BankStatement").ToList();
var orgauthlist = db.Queryable<SysOrgAuth>().ClearFilter().Where(t => t.Deleted == false && t.Type == Module.Core.Enums.OrgAuthTypeEnum.BankStatement).ToList();
//遍历授权数据集

@ -1,5 +1,6 @@
using DS.Module.Core.Enums;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Fee.Method;
using DS.WMS.Core.QuarztJobs.Dtos;
using DS.WMS.Core.QuarztJobs.Interface;
using DS.WMS.Core.QuarztJobs.Other;
@ -9,6 +10,7 @@ using Newtonsoft.Json;
using SqlSugar;
using System.Net.Http.Headers;
namespace DS.WMS.Core.QuarztJobs.Method
{
/// <summary>
@ -37,11 +39,16 @@ namespace DS.WMS.Core.QuarztJobs.Method
return;
}
var orgauthlist= db.Queryable<SysOrgAuth>().ClearFilter().Where(t => t.Deleted == false&&t.Type=="ininvice").ToList();
var orgauthlist= db.Queryable<SysOrgAuth>().ClearFilter().Where(t => t.Deleted == false&&t.Type==OrgAuthTypeEnum.InInvoice).ToList();
//遍历授权数据集
foreach (var item in orgauthlist)
{
bool tb = false; //根据此字段判断是否需要同步发票数据到钉钉
//组织请求远程接口api数据
Dictionary<string, string> header = new Dictionary<string, string>();
header.Add("USER_KEY", item.Key);
@ -80,8 +87,10 @@ namespace DS.WMS.Core.QuarztJobs.Method
gidi.fphm = itemdata.fphm;
var resultinfo = await HttpHellp.PostAsync("http://47.105.115.105:26650/api/XSD/GetInInvoiceDataInfo", JsonConvert.SerializeObject(gidi), header);
var Iinfo = JsonConvert.DeserializeObject<InInvoiceDataInfoOutput>(resultinfo);
if (Iinfo.code == 0) //调整
{
if (Iinfo.success == true)
{
tb = true;
//添加发票数据
InInvoice inInvoice = new InInvoice();
inInvoice.InvoicingDate = Iinfo.data.kprq;
@ -175,12 +184,50 @@ namespace DS.WMS.Core.QuarztJobs.Method
inInvoicedtl.CreateTime = DateTime.Now;
await tenantDb.Insertable(inInvoicedtl).ExecuteCommandAsync();
}
}
}
}
if (tb)
{
try
{
#region 同步发票到钉钉审批
var dingconfig = db.Queryable<SysOrgAuth>().Where(t => t.Type == OrgAuthTypeEnum.DingConfig &&t.OrgId==item.OrgId).First();
if (dingconfig!=null)
{
//获取钉钉密钥
var token = DingDing.GetDingToken(dingconfig.Key, dingconfig.Secret);
//获取对应的组织机构的发票列表
var ininviceList = await tenantDb.Queryable<InInvoice>().Where(x => x.ReimbursementType == ReimbursementTypeEnums.NotSubmitted && x.OrgId == item.OrgId).ToListAsync();
//将发票信息同步更新到钉钉
var DingProcess = db.Queryable<SysOrgAuth>().Where(t => t.Type == OrgAuthTypeEnum.DingProcessCode && t.OrgId == item.OrgId).First();
DingDing.UpDingOAForm(token, DingProcess.Key, ininviceList);
}
#endregion
}
catch (Exception ex)
{
throw;
}
}
}
}
}
}

@ -1,4 +1,5 @@
using DS.Module.Core.Data;
using DS.Module.Core.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
@ -20,7 +21,9 @@ namespace DS.WMS.Core.Sys.Entity
/// <summary>
/// 类型
/// </summary>
public string Type { get; set; }
public OrgAuthTypeEnum Type { get; set; }
/// <summary>
/// 请求key
/// </summary>

@ -616,7 +616,7 @@ namespace DS.WMS.Core.TaskPlat.Method
}
// 获取任务流水号
DataResult<string> sequence = commonService.GetSequenceNext<TaskBaseInfo>(tenantDb, user);
DataResult<string> sequence = await commonService.GetSequenceNextAsync<TaskBaseInfo>(tenantDb, user);
string taskNo = sequence.Data ?? "";
if (string.IsNullOrEmpty(taskNo))

@ -34,7 +34,7 @@ namespace DS.WMS.FeeApi.Controllers
[HttpPost]
[Route("GetReimbursementList")]
public DataResult<List<ReimbursementRes>> GetReimbursementList([FromBody] PageRequest request)
{
{
var res = _service.GetListByPage(request);
return res;
}
@ -85,9 +85,9 @@ namespace DS.WMS.FeeApi.Controllers
/// <returns></returns>
[HttpPost]
[Route("ReimbursementRevoked")]
public async Task<DataResult> ReimbursementRevoked([FromBody] string id)
public async Task<DataResult> ReimbursementRevoked([FromBody] ReimbursementRevokedInput Model)
{
var res = await _service.ReimbursementRevoked(id);
var res = await _service.ReimbursementRevoked(Model.Id);
return res;
}
@ -97,7 +97,7 @@ namespace DS.WMS.FeeApi.Controllers
/// <param name="request"></param>
/// <returns></returns>
[HttpPost, Route("Audit")]
public async Task<DataResult> AuditAsync([FromBody] AuditRequest request)
public async Task<DataResult> AuditAsync([FromBody] ReimbursementAuditRequest request)
{
if (request.Ids.Length == 0 || (request.Result != 1 && request.Result != 2))
return DataResult.Failed("参数无效", MultiLanguageConst.IllegalRequest);

Loading…
Cancel
Save