558 lines
22 KiB
C#
558 lines
22 KiB
C#
|
|
|
|
using ServerCore;
|
|
using ServerBase;
|
|
using ServerCommon;
|
|
using ServerCommon.BusinessLogDomain;
|
|
using MetaAssets;
|
|
|
|
|
|
using META_ID = System.UInt32;
|
|
|
|
|
|
namespace GameServer;
|
|
|
|
public class PackageAction : EntityActionBase
|
|
{
|
|
private List<PackageRepeat> m_repeat_packages = new ();
|
|
|
|
public PackageAction(Player owner)
|
|
: base(owner)
|
|
{
|
|
}
|
|
|
|
public override void onClear()
|
|
{
|
|
m_repeat_packages.Clear();
|
|
return;
|
|
}
|
|
|
|
public override async Task<Result> onInit()
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
var result = new Result();
|
|
|
|
return result;
|
|
}
|
|
|
|
public void addPackage(PackageRepeat packageRepeat)
|
|
{
|
|
m_repeat_packages.Add(packageRepeat);
|
|
}
|
|
|
|
public async Task<Result> InsertPackageLastOrderRecodeDoc()
|
|
{
|
|
var result = new Result();
|
|
var player = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(player);
|
|
|
|
var package_last_order_recode_attribute = player.getEntityAttribute<PackageLastOrderRecodeAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(package_last_order_recode_attribute, () => $"package_last_order_recode_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
var package_last_order_recode_doc = package_last_order_recode_attribute.getOriginDocBase<PackageLastOrderRecodeAttribute>();
|
|
if (package_last_order_recode_doc == null)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var dynamo_db_client = server_logic.getDynamoDbClient();
|
|
ArgumentNullException.ThrowIfNull(dynamo_db_client);
|
|
|
|
result = await dynamo_db_client.simpleInsertDocumentWithDocType(new PackageLastOrderRecodeDoc(player.getUserGuid()));
|
|
if (result.isFail())
|
|
{
|
|
var err_msg = $"Failed to simpleUpsertDocumentWithDocType<PackageLastOrderRecodeDoc> !!! - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> AddPackageFromDocs(List<PackageRepeatDoc> packageDocs)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(player);
|
|
|
|
foreach (var package_repeat_doc in packageDocs)
|
|
{
|
|
(result, var package_repeat) = await PackageRepeat.createPackageRepeatFromDoc(player, package_repeat_doc);
|
|
if (result.isFail()) return result;
|
|
|
|
NullReferenceCheckHelper.throwIfNull(package_repeat, () => $"package_repeat is null !!! - {player.toBasicString()}");
|
|
|
|
m_repeat_packages.Add(package_repeat);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<(Result, PackageRepeat?, List<DynamoDbDocBase>?)> tryOrderNewProduct(string order_guid, META_ID product_meta_id, DateTime buyDateTime, List<ILogInvoker> invokers)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(player);
|
|
|
|
if (MetaData.Instance._ProductMetaDataById.TryGetValue((int)product_meta_id, out var productMetaData) == false)
|
|
{
|
|
err_msg = $"Failed to find product meta Id. meta_id : {product_meta_id}";
|
|
result.setFail(ServerErrorCode.NotFoundItemTableId, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, null, null);
|
|
}
|
|
|
|
(result, var new_package_repeat, var receivedMailDocs) = await newGiveProduct(productMetaData, order_guid, buyDateTime);
|
|
if (result.isFail()) return (result, null, null);
|
|
|
|
foreach (var receivedMailDoc in receivedMailDocs)
|
|
{
|
|
var mail_doc = receivedMailDoc as MailDoc;
|
|
ArgumentNullException.ThrowIfNull(mail_doc);
|
|
var task_mail_log_data = MailBusinessLogHelper.toMailLogInfo(mail_doc);
|
|
ArgumentNullException.ThrowIfNull(task_mail_log_data);
|
|
invokers.Add(new MailBusinessLog(task_mail_log_data));
|
|
}
|
|
|
|
var task_state_log_data = PackageBusinessLogHelper.toStateLogInfo(order_guid, BillingStateType.received, string.Empty);
|
|
ArgumentNullException.ThrowIfNull(task_state_log_data);
|
|
invokers.Add(new PackageStateBusinessLog(task_state_log_data));
|
|
|
|
if (new_package_repeat != null)
|
|
{
|
|
var package_repeat_attribute = new_package_repeat.getEntityAttribute<PackageRepeatAttribute>();
|
|
ArgumentNullException.ThrowIfNull(package_repeat_attribute);
|
|
|
|
var task_repeat_log_data = PackageBusinessLogHelper.toRepeatLogInfo(package_repeat_attribute);
|
|
invokers.Add(new PackageRepeatBusinessLog(task_repeat_log_data));
|
|
}
|
|
|
|
var package_lastorder_recode_attribute = player.getEntityAttribute<PackageLastOrderRecodeAttribute>();
|
|
ArgumentNullException.ThrowIfNull(package_lastorder_recode_attribute);
|
|
|
|
package_lastorder_recode_attribute.LastOrderGuid = order_guid;
|
|
package_lastorder_recode_attribute.LastBuyTime = buyDateTime;
|
|
package_lastorder_recode_attribute.modifiedEntityAttribute();
|
|
|
|
return (result, new_package_repeat, receivedMailDocs);
|
|
}
|
|
|
|
public async Task<Result> tryOrderNewProductList()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(player);
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
ArgumentNullException.ThrowIfNull(server_logic);
|
|
|
|
var mail_action = player.getEntityAction<MailAction>();
|
|
ArgumentNullException.ThrowIfNull(mail_action);
|
|
|
|
var account_attribute = player.getEntityAttribute<AccountAttribute>();
|
|
ArgumentNullException.ThrowIfNull(account_attribute);
|
|
|
|
var package_lastorder_recode_attribute = player.getEntityAttribute<PackageLastOrderRecodeAttribute>();
|
|
ArgumentNullException.ThrowIfNull(package_lastorder_recode_attribute);
|
|
|
|
var jwt = account_attribute.SsoAccountAuthJWT.ToString();
|
|
var account_id = account_attribute.AccountId;
|
|
|
|
if(jwt == string.Empty)
|
|
return result;
|
|
|
|
//BillingServer에 구매내역 조회
|
|
var billingPurchaseRequest = new BillingPurchaseRequest() { account_id = account_id.ToString(), order_id = package_lastorder_recode_attribute.LastOrderGuid };
|
|
(result, var billingPurchaseInfo) = await BillingServerConnector.GetBillingPurchaseInfos(billingPurchaseRequest, jwt);
|
|
if (result.isFail())
|
|
return result;
|
|
|
|
NullReferenceCheckHelper.throwIfNull(billingPurchaseInfo, () => $"billingPurchaseInfo is null !!! - {player.toBasicString()}");
|
|
if (billingPurchaseInfo.data.Count == 0)
|
|
return result;
|
|
|
|
(result, var order_id_list) = await mail_action.getReceivedProductMailOrderIds();
|
|
if (result.isFail())
|
|
return result;
|
|
|
|
var fn_give_product = async delegate ()
|
|
{
|
|
var result = new Result();
|
|
|
|
var invokers = new List<ILogInvoker>();
|
|
var new_package_repeats = new List<PackageRepeat>();
|
|
var received_mail_docs = new List<DynamoDbDocBase>();
|
|
var last_order_product_meta_id = 0;
|
|
var last_order_id = "";
|
|
var last_order_buy_time = DateTime.UtcNow;
|
|
var now = DateTime.UtcNow;
|
|
|
|
foreach (var order_info in billingPurchaseInfo.data)
|
|
{
|
|
if (EnumHelper.tryParse<BillingStateType>(order_info.state, out var state) == false)
|
|
{
|
|
result.setFail(ServerErrorCode.BillingInvalidStateType, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return result;
|
|
}
|
|
|
|
if (state != BillingStateType.paid)
|
|
continue;
|
|
|
|
last_order_buy_time = DateTimeOffset.FromUnixTimeSeconds(order_info.buyDateTime).UtcDateTime;
|
|
if(int.TryParse(order_info.product_meta_id, out last_order_product_meta_id) == false)
|
|
{
|
|
result.setFail(ServerErrorCode.BillingFailedParseProductMetaIdType, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return result;
|
|
}
|
|
|
|
bool isAlreadyReceivedMail = false;
|
|
|
|
foreach (var order_id in order_id_list)
|
|
{
|
|
if(order_info.order_id == order_id)
|
|
{
|
|
isAlreadyReceivedMail = true;
|
|
|
|
var stateList = new List<BillingStateList>() { new BillingStateList() { order_id = order_info.order_id, state = BillingStateType.received.ToString() } };
|
|
var billingChangeState = new BillingChangeState() { account_id = account_id.ToString(), state_list = stateList };
|
|
(result, var status_message) = await BillingServerConnector.UpdateBillingState(billingChangeState, jwt);
|
|
if (result.isFail())
|
|
break;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(isAlreadyReceivedMail == true)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
(result, var new_package_repeat, var receivedMailDocs) = await tryOrderNewProduct(order_info.order_id, (META_ID)last_order_product_meta_id, now, invokers);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(receivedMailDocs, () => $"receivedMailDocs is null !!!");
|
|
|
|
if (new_package_repeat != null)
|
|
{
|
|
new_package_repeats.Add(new_package_repeat);
|
|
}
|
|
received_mail_docs.AddRange(receivedMailDocs);
|
|
last_order_id = order_info.order_id;
|
|
}
|
|
|
|
if(received_mail_docs.Count == 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var task_log_data = PackageBusinessLogHelper.toLastOrderRecodeLogInfo(last_order_id, (META_ID)last_order_product_meta_id, last_order_buy_time, now);
|
|
ArgumentNullException.ThrowIfNull(task_log_data, $"task_log_data is null !!!");
|
|
invokers.Add(new PackageLastOrderRecordBusinessLog(task_log_data));
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.ProductGive
|
|
, server_logic.getDynamoDbClient(), true);
|
|
{
|
|
batch.addQuery(new DBQEntityWrite(received_mail_docs));
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
}
|
|
|
|
batch.appendBusinessLogs(invokers);
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//BillingServer에 상태값 갱신
|
|
foreach (var order_info in billingPurchaseInfo.data)
|
|
{
|
|
(result, var isUpdated) = await BillingServerConnector.AbleToChangeBillingState(jwt, account_id.ToString(), order_info.order_id, BillingStateType.received);
|
|
if (result.isFail() || isUpdated == true)
|
|
continue;
|
|
|
|
var stateList = new List<BillingStateList>() { new BillingStateList() { order_id = order_info.order_id, state = BillingStateType.received.ToString() } };
|
|
var billingChangeState = new BillingChangeState() { account_id = account_id.ToString(), state_list = stateList };
|
|
(result, var status_message) = await BillingServerConnector.UpdateBillingState(billingChangeState, jwt);
|
|
if (result.isFail())
|
|
continue;
|
|
}
|
|
|
|
foreach (var new_package_repeat in new_package_repeats)
|
|
{
|
|
m_repeat_packages.Add(new_package_repeat);
|
|
}
|
|
mail_action.NewReceivedMail();
|
|
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "give_product", fn_give_product);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> UpdateTick()
|
|
{
|
|
return await UpdateRepeatProduct();
|
|
}
|
|
|
|
public async Task<Result> UpdateRepeatProduct()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(player);
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
if (m_repeat_packages.Count == 0)
|
|
return result;
|
|
ArgumentNullException.ThrowIfNull(server_logic, $"server_logic is null !!!");
|
|
|
|
if (isUpdateRepeatProduct() == false)
|
|
return result;
|
|
|
|
var fn_update_give_product = async delegate ()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var invokers = new List<ILogInvoker>();
|
|
var mail_docs = new List<DynamoDbDocBase>();
|
|
var remove_packages = new List<PackageRepeat>();
|
|
|
|
var mail_action = player.getEntityAction<MailAction>();
|
|
ArgumentNullException.ThrowIfNull(mail_action);
|
|
|
|
var copy_packages = m_repeat_packages.ToList();
|
|
|
|
foreach (var package in copy_packages)
|
|
{
|
|
var package_attribute = package.getEntityAttribute<PackageRepeatAttribute>();
|
|
ArgumentNullException.ThrowIfNull(package_attribute);
|
|
|
|
if (MetaData.Instance._ProductMetaDataById.TryGetValue((int)package_attribute.ProductMetaId, out var productMetaData) == false)
|
|
{
|
|
err_msg = $"Failed to find product meta Id. meta_id : {package_attribute.ProductMetaId}";
|
|
result.setFail(ServerErrorCode.NotFoundItemTableId, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return result;
|
|
}
|
|
|
|
(result, var receivedMailDocs, bool isDeleteRepeat) = await updateGiveProduct(productMetaData, package_attribute, package_attribute.OrderGuid, invokers);
|
|
if (result.isFail()) return result;
|
|
|
|
mail_docs.AddRange(receivedMailDocs);
|
|
|
|
if (isDeleteRepeat == true)
|
|
{
|
|
remove_packages.Add(package);
|
|
}
|
|
|
|
var task_log_data = PackageBusinessLogHelper.toRepeatLogInfo(package_attribute);
|
|
invokers.Add(new PackageRepeatBusinessLog(task_log_data));
|
|
}
|
|
|
|
if (mail_docs.Count == 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.ProductGive
|
|
, server_logic.getDynamoDbClient());
|
|
{
|
|
batch.addQuery(new DBQEntityWrite(mail_docs));
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
}
|
|
|
|
batch.appendBusinessLogs(invokers);
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail()) return result;
|
|
|
|
foreach (var remove_package in remove_packages)
|
|
{
|
|
m_repeat_packages.Remove(remove_package);
|
|
}
|
|
|
|
mail_action.NewReceivedMail();
|
|
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "update_give_product", fn_update_give_product);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task<(Result, PackageRepeat?, List<DynamoDbDocBase>)> newGiveProduct(ProductMetaData productMetaData, string order_guid, DateTime buyDateTime)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(player);
|
|
|
|
var mail_action = player.getEntityAction<MailAction>();
|
|
ArgumentNullException.ThrowIfNull(mail_action);
|
|
var receivedMailDocs = new List<DynamoDbDocBase>();
|
|
|
|
if(productMetaData.ItemID_First != 0)
|
|
{
|
|
var expireDate = DateTimeHelper.MaxTime;
|
|
if (productMetaData.Storage_Period_First != 0)
|
|
expireDate = buyDateTime.AddMinutes(productMetaData.Storage_Period_First);
|
|
|
|
var mail_Items = new List<ServerCommon.MailItem>() { new ServerCommon.MailItem() { ItemId = (META_ID)productMetaData.ItemID_First, Count = 1, ProductId = (META_ID)productMetaData.Id, isRepeatProduct = false } };
|
|
(result, var firstReceivedMailDoc) = await mail_action.tryMakeNewSystemMail(mail_Items, productMetaData.SystemMail_First, expireDate, order_guid);
|
|
if (result.isFail()) return (result, null, receivedMailDocs);
|
|
NullReferenceCheckHelper.throwIfNull(firstReceivedMailDoc, () => $"firstReceivedMailDoc is null !!!");
|
|
|
|
receivedMailDocs.Add(firstReceivedMailDoc);
|
|
}
|
|
|
|
var nowTime = DateTime.UtcNow;
|
|
var next_give_time = buyDateTime;
|
|
var repeat_count = productMetaData.Mail_Repeat_Count;
|
|
var left_count = productMetaData.Mail_Repeat_Count;
|
|
|
|
for (int i = 0; i < repeat_count; ++i)
|
|
{
|
|
if (nowTime < next_give_time)
|
|
{
|
|
break;
|
|
}
|
|
|
|
var expireDate = DateTimeHelper.MaxTime;
|
|
if (productMetaData.Storage_Period_Repeat != 0)
|
|
expireDate = next_give_time.AddMinutes(productMetaData.Storage_Period_Repeat);
|
|
|
|
var mail_Items = new List<ServerCommon.MailItem>() { new ServerCommon.MailItem() { ItemId = (META_ID)productMetaData.ItemID_Repeat, Count = 1, ProductId = (META_ID)productMetaData.Id, isRepeatProduct = true } };
|
|
(result, var receivedMailDoc) = await mail_action.tryMakeNewSystemMail(mail_Items,productMetaData.SystemMail_Repeat, expireDate, order_guid);
|
|
if (result.isFail()) return (result, null, receivedMailDocs);
|
|
NullReferenceCheckHelper.throwIfNull(receivedMailDoc, () => $"receivedMailDoc is null !!!");
|
|
|
|
receivedMailDocs.Add(receivedMailDoc);
|
|
|
|
--left_count;
|
|
next_give_time = next_give_time.AddMinutes(productMetaData.Mail_Repeat_Interval);
|
|
}
|
|
|
|
if (left_count <= 0)
|
|
{
|
|
return (result, null, receivedMailDocs);
|
|
}
|
|
|
|
(result, var package) = await PackageRepeat.createPackageRepeat(player, order_guid, (META_ID)productMetaData.Id, left_count, next_give_time);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null, receivedMailDocs);
|
|
}
|
|
|
|
return (result, package, receivedMailDocs);
|
|
}
|
|
|
|
public bool isUpdateRepeatProduct()
|
|
{
|
|
var copy_packages = m_repeat_packages.ToList();
|
|
var nowTime = DateTime.UtcNow;
|
|
|
|
foreach (var package in copy_packages)
|
|
{
|
|
var package_attribute = package.getEntityAttribute<PackageRepeatAttribute>();
|
|
ArgumentNullException.ThrowIfNull(package_attribute);
|
|
|
|
if (nowTime < package_attribute.NextGiveTime)
|
|
continue;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private async Task<(Result, List<DynamoDbDocBase>, bool isDeleteRepeat)> updateGiveProduct(ProductMetaData productMetaData, PackageRepeatAttribute package_attribute, string order_guid, List<ILogInvoker> invokers)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(player);
|
|
var receivedMailDocs = new List<DynamoDbDocBase>();
|
|
|
|
var nowTime = DateTime.UtcNow;
|
|
var next_give_time = package_attribute.NextGiveTime;
|
|
var repeat_count = package_attribute.LeftCount;
|
|
var left_count = package_attribute.LeftCount;
|
|
|
|
for (int i = 0; i < repeat_count; ++i)
|
|
{
|
|
if (nowTime < next_give_time)
|
|
break;
|
|
|
|
--left_count;
|
|
var expireDate = DateTimeHelper.MaxTime;
|
|
if (productMetaData.Storage_Period_Repeat != 0)
|
|
expireDate = next_give_time.AddMinutes(productMetaData.Storage_Period_Repeat);
|
|
next_give_time = next_give_time.AddMinutes(productMetaData.Mail_Repeat_Interval);
|
|
|
|
if (expireDate < nowTime)
|
|
{
|
|
var task_mail_expired_log_data = MailBusinessLogHelper.toMailExpiredLogInfo(order_guid, productMetaData.Id, next_give_time, expireDate, nowTime, left_count);
|
|
invokers.Add(new MailExpiredBusinessLog(task_mail_expired_log_data));
|
|
continue;
|
|
}
|
|
|
|
var mail_action = player.getEntityAction<MailAction>();
|
|
var mail_Items = new List<ServerCommon.MailItem>() { new ServerCommon.MailItem() { ItemId = (META_ID)productMetaData.ItemID_Repeat, Count = 1, ProductId = (META_ID)productMetaData.Id, isRepeatProduct = true } };
|
|
(result, var receivedMailDoc) = await mail_action.tryMakeNewSystemMail(mail_Items, productMetaData.SystemMail_Repeat, expireDate, order_guid);
|
|
NullReferenceCheckHelper.throwIfNull(receivedMailDoc, () => $"receivedMailDoc is null !!! - {player.toBasicString()}");
|
|
|
|
receivedMailDocs.Add(receivedMailDoc);
|
|
}
|
|
|
|
foreach (var receivedMailDoc in receivedMailDocs)
|
|
{
|
|
var mail_doc = receivedMailDoc as MailDoc;
|
|
ArgumentNullException.ThrowIfNull(mail_doc);
|
|
var task_mail_log_data = MailBusinessLogHelper.toMailLogInfo(mail_doc);
|
|
invokers.Add(new MailBusinessLog(task_mail_log_data));
|
|
}
|
|
|
|
if (left_count <= 0)
|
|
{
|
|
package_attribute.deleteEntityAttribute();
|
|
return (result, receivedMailDocs, true);
|
|
}
|
|
else
|
|
{
|
|
package_attribute.NextGiveTime = next_give_time;
|
|
package_attribute.LeftCount = left_count;
|
|
package_attribute.modifiedEntityAttribute();
|
|
return (result, receivedMailDocs, false);
|
|
}
|
|
}
|
|
}
|