using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Google.Protobuf.WellKnownTypes; using Newtonsoft.Json; using ServerCore; using ServerBase; using ServerCommon.BusinessLogDomain; using USER_GUID = System.String; using Amazon.S3.Model; using System.Runtime.InteropServices; namespace ServerCommon { public class ShopProductTradingMeterSubAttribute { [JsonProperty("product_id")] public int ProductId { get; set; } [JsonProperty("left_count")] public double LeftCount { get; set; } } public class ShopProductTradingMeterAttribute : EntityAttributeBase, ICopyEntityAttributeFromDoc, IMergeWithEntityAttribute { private readonly USER_GUID m_user_guid; [JsonProperty] public int ShopId { get; set; } [JsonProperty] public Timestamp EndTime { get; set; } = DateTimeHelper.MinTime.ToTimestamp(); [JsonProperty] public List ShopProductTradingMeterSubs { get; private set; } = new(); [JsonProperty] public Int32 CurrentRenewalCount { get; private set; } = 0; public ShopProductTradingMeterAttribute( EntityBase owner, USER_GUID user_guid , EntityBase entityOfOwnerEntityType ) : base(owner, entityOfOwnerEntityType) { m_user_guid = user_guid; } public override void onClear() { ShopId = 0; EndTime = DateTimeHelper.MinTime.ToTimestamp(); ShopProductTradingMeterSubs.Clear(); CurrentRenewalCount = 0; getAttributeState().reset(); } public override EntityAttributeBase onCloned() { var owner_entity_type = getEntityOfOwnerEntityType(); NullReferenceCheckHelper.throwIfNull(owner_entity_type, () => $"owner_entity_type is null !!!"); var cloned = new ShopProductTradingMeterAttribute( getOwner() , m_user_guid, owner_entity_type) { ShopId = ShopId, EndTime = EndTime, CurrentRenewalCount = CurrentRenewalCount }; foreach (var sub in ShopProductTradingMeterSubs) { var data = new ShopProductTradingMeterSubAttribute { ProductId = sub.ProductId, LeftCount = sub.LeftCount }; cloned.ShopProductTradingMeterSubs.Add(data); } return cloned; } public override IEntityAttributeTransactor onNewEntityAttributeTransactor() { return new ShopProductTradingMeterAttributeTransactor(getOwner()); } public override async Task<(Result, DynamoDbDocBase?)> toDocBase(bool isForQuery = true) { var result = new Result(); //===================================================================================== // Attribute => try pending Doc //===================================================================================== var try_pending_doc = getTryPendingDocBase() as ShopProductTradingMeterDoc; if (null == try_pending_doc) { var to_copy_doc = new ShopProductTradingMeterDoc(m_user_guid, ShopId); var origin_doc = getOriginDocBase(); if (null != origin_doc) { to_copy_doc.copyTimestampsFromOriginDocBase(origin_doc); } to_copy_doc.onApplyPKSK(); try_pending_doc = to_copy_doc; setTryPendingDocBase(try_pending_doc); } var to_copy_doc_attrib = try_pending_doc.getAttrib(); NullReferenceCheckHelper.throwIfNull(to_copy_doc_attrib, () => $"to_copy_doc_attrib is null !!!"); to_copy_doc_attrib.onClear(); to_copy_doc_attrib.ShopId = ShopId; to_copy_doc_attrib.EndTime = EndTime; to_copy_doc_attrib.CurrentRenewalCount = CurrentRenewalCount; foreach (var sub in ShopProductTradingMeterSubs) { to_copy_doc_attrib.ShopProductTradingMeterSubs.Add(new ShopProductTradingMeterSubAttrib { ProductId = sub.ProductId, LeftCount = sub.LeftCount }); } if (false == isForQuery) { return (result, try_pending_doc); } //===================================================================================== // Doc QueryType 반영 //===================================================================================== (result, var to_query_doc) = await applyDoc4Query(try_pending_doc); if (result.isFail()) { return (result, null); } return (result, to_query_doc); } public Result onMerge(EntityAttributeBase otherEntityAttribute) { var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var result = new Result(); string err_msg; //===================================================================================== // OtherAttribute => Attribute //===================================================================================== var other_shop_product_trading_meter_attribute = otherEntityAttribute as ShopProductTradingMeterAttribute; if (null == other_shop_product_trading_meter_attribute) { err_msg = $"Failed to cast ShopProductTradingMeterAttribute !!!, other_shop_product_trading_meter_attribute is null"; result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg); Log.getLogger().error(result.toBasicString()); return result; } onClear(); ShopId = other_shop_product_trading_meter_attribute.ShopId; EndTime = other_shop_product_trading_meter_attribute.EndTime; CurrentRenewalCount = other_shop_product_trading_meter_attribute.CurrentRenewalCount; foreach (var subAttribute in other_shop_product_trading_meter_attribute.ShopProductTradingMeterSubs) { var data = new ShopProductTradingMeterSubAttribute(); data.ProductId = subAttribute.ProductId; data.LeftCount = subAttribute.LeftCount; ShopProductTradingMeterSubs.Add(data); } //===================================================================================== // Attribute Try Pending Doc => Origin Doc //===================================================================================== var try_pending_doc = other_shop_product_trading_meter_attribute.getTryPendingDocBase() as ShopProductTradingMeterDoc; if (null != try_pending_doc) { other_shop_product_trading_meter_attribute.resetTryPendingDocBase(); syncOriginDocBaseWithNewDoc(try_pending_doc); } var origin_doc_base = getOriginDocBase(); if (null == origin_doc_base) { // DB 에 저장되어 있지 않는 경우 OriginDoc은 null 이다 !!! return result; } var shop_product_trading_meter_attrib = origin_doc_base.getAttrib(); NullReferenceCheckHelper.throwIfNull(shop_product_trading_meter_attrib, () => $"shop_product_trading_meter_attrib is null !!! - {owner.toBasicString()}"); shop_product_trading_meter_attrib.ShopId = ShopId; shop_product_trading_meter_attrib.EndTime = EndTime; shop_product_trading_meter_attrib.CurrentRenewalCount = CurrentRenewalCount; foreach(var sub in ShopProductTradingMeterSubs) { var data = new ShopProductTradingMeterSubAttrib(); data.ProductId = sub.ProductId; data.LeftCount = sub.LeftCount; shop_product_trading_meter_attrib.ShopProductTradingMeterSubs.Add(data); } return result; } public bool copyEntityAttributeFromDoc(DynamoDbDocBase? docBase) { if (docBase is not ShopProductTradingMeterDoc meterDoc) { var err_msg = $"Failed to copyEntityAttributeFromDoc() !!!, shop_product_trading_meter_doc is null :{nameof(ShopProductTradingMeterDoc)}"; Log.getLogger().error(err_msg); return false; } //===================================================================================== // New Doc => Origin Doc //===================================================================================== syncOriginDocBaseWithNewDoc(meterDoc); //===================================================================================== // Doc => Attribute //===================================================================================== var attr = meterDoc.getAttrib(); if (null == attr) { var err_msg = $"Failed to copyEntityAttributeFromDocs() !!!, not found doc attrib !!! :{toBasicString()}"; Log.getLogger().error(err_msg); return false; } onClear(); ShopId = attr.ShopId; EndTime = attr.EndTime; CurrentRenewalCount = attr.CurrentRenewalCount; foreach (var meter in attr.ShopProductTradingMeterSubs) { var info = new ShopProductTradingMeterSubAttribute { ProductId = meter.ProductId, LeftCount = meter.LeftCount }; ShopProductTradingMeterSubs.Add(info); } return true; } public Result changeProductTradingMeter(int product_id, int delta) { var result = new Result(); string err_msg; var meter = findMeter(product_id); if (null == meter) { err_msg = $"Failed to found product id: {product_id}"; result.setFail(ServerErrorCode.NotFoundProductId, err_msg); Log.getLogger().error(err_msg); return result; } var change = meter.LeftCount + delta; if (change < 0) { err_msg = $"Failed to change shop meter !!! : Invalid count - {meter.LeftCount} / {delta}"; result.setFail(ServerErrorCode.InvalidArgument, err_msg); return result; } meter.LeftCount += delta; return result; } public ShopProductTradingMeterSubAttribute? getMeterSubAttribute(int product_id) => ShopProductTradingMeterSubs.FirstOrDefault(sub => sub.ProductId == product_id); public void initEndTime() => EndTime = Timestamp.FromDateTime(DateTime.UtcNow); public void initRenewalCount() => CurrentRenewalCount = 0; public void increaseRenewalCount(Int32 increaseCount = 1) { CurrentRenewalCount += increaseCount; } public void setCurrentRenewalCount(Int32 currenctRenewalCount) { CurrentRenewalCount = currenctRenewalCount; } private ShopProductTradingMeterSubAttribute? findMeter(int product_id) => ShopProductTradingMeterSubs.FirstOrDefault(meter => meter.ProductId == product_id); } public class ShopProductTradingMeterAttributeTransactor : EntityAttributeTransactorBase, ICopyEntityAttributeTransactorFromEntityAttribute { public ShopProductTradingMeterAttributeTransactor(EntityBase owner) : base(owner) { } public bool copyEntityAttributeTransactorFromEntityAttribute(EntityAttributeBase entityAttributeBase) { string err_msg; var copy_from_shop_product_trading_meter_attribute = entityAttributeBase as ShopProductTradingMeterAttribute; if (null == copy_from_shop_product_trading_meter_attribute) { err_msg = $"Failed to copyEntityAttributeTransactorFromEntityAttribute() !!!, copy_from_shop_product_trading_meter_attribute is null :{nameof(ShopProductTradingMeterAttribute)}"; Log.getLogger().error(err_msg); return false; } var copy_to_shop_product_trading_meter_attribute = getClonedEntityAttribute() as ShopProductTradingMeterAttribute; if (null == copy_to_shop_product_trading_meter_attribute) { err_msg = $"Failed to copyEntityAttributeTransactorFromEntityAttribute() !!!, copy_to_shop_product_trading_meter_attribute is null :{nameof(ShopProductTradingMeterAttribute)}"; Log.getLogger().error(err_msg); return false; } copy_to_shop_product_trading_meter_attribute.onClear(); copy_to_shop_product_trading_meter_attribute.ShopId = copy_from_shop_product_trading_meter_attribute.ShopId; copy_to_shop_product_trading_meter_attribute.EndTime = copy_from_shop_product_trading_meter_attribute.EndTime; copy_to_shop_product_trading_meter_attribute.setCurrentRenewalCount(copy_from_shop_product_trading_meter_attribute.CurrentRenewalCount); foreach (var subAttribute in copy_from_shop_product_trading_meter_attribute.ShopProductTradingMeterSubs) { var data = new ShopProductTradingMeterSubAttribute(); data.ProductId = subAttribute.ProductId; data.LeftCount = subAttribute.LeftCount; copy_to_shop_product_trading_meter_attribute.ShopProductTradingMeterSubs.Add(data); } return true; } } }