public async Task <MCommunication_Alert> GetAlertAsync(long alertId)
        {
            using var log = BeginFunction(nameof(CommunicationMicroService), nameof(GetAlertAsync), alertId);
            try
            {
                using var ctx = QuiltContextFactory.Create();

                var dbAlert = await ctx.Alerts.Where(r => r.AlertId == alertId).FirstAsync().ConfigureAwait(false);

                var alert = Create.MCommunication_Alert(dbAlert);

                var result = alert;

                log.Result(result);

                return(result);
            }
            catch (Exception ex)
            {
                log.Exception(ex);
                throw;
            }
        }
        public async Task <byte[]> GetDesignSnapshotThumbnailAsync(int designSnapshotId, int thumbnailSize)
        {
            using var log = BeginFunction(nameof(DesignMicroService), nameof(GetDesignSnapshotThumbnailAsync), designSnapshotId, thumbnailSize);
            try
            {
                using var ctx = QuiltContextFactory.Create();

                var dbDesignSnapshot = await ctx.DesignSnapshots.Where(r => r.DesignSnapshotId == designSnapshotId).SingleOrDefaultAsync().ConfigureAwait(false);

                if (dbDesignSnapshot == null)
                {
                    return(null);
                }

                var json   = JToken.Parse(dbDesignSnapshot.Artifact.Value);
                var design = new Design.Core.Design(json);

                //Logger.LogMessage("Artifact parsed.");

                var renderer = new DesignRenderer();

                using var image = renderer.CreateBitmap(design, thumbnailSize, false);
                using var ms    = new MemoryStream();

                image.Save(ms, ImageFormat.Png);
                var result = ms.ToArray();

                log.Result(result);

                return(result);
            }
            catch (Exception ex)
            {
                log.Exception(ex);
                throw;
            }
        }
        public async Task <MProject_Project> GetProjectAsync(Guid projectId)
        {
            using var ctx = QuiltContextFactory.Create();

            var projectSnapshotId = await ctx.Projects
                                    .Where(r => r.ProjectId == projectId)
                                    .Join(
                ctx.ProjectSnapshots,
                project => new { project.ProjectId, Sequence = project.CurrentProjectSnapshotSequence },
                projectSnapshot => new { projectSnapshot.ProjectId, Sequence = projectSnapshot.ProjectSnapshotSequence },
                (project, projectSnapshot) => projectSnapshot.ProjectSnapshotId)
                                    .SingleAsync().ConfigureAwait(false);

            var mProject = await ctx.ProjectSnapshots
                           .Include(r => r.Artifact)
                           .Include(r => r.DesignSnapshot)
                           .ThenInclude(r => r.Artifact)
                           .Include(r => r.ProjectSnapshotComponents)
                           .Where(r => r.ProjectSnapshotId == projectSnapshotId)
                           .Select(r => Create.MProject_Project(r))
                           .SingleOrDefaultAsync().ConfigureAwait(false);

            return(mProject);
        }
        public async Task <MDesign_Design> GetDesignAsync(int designSnapshotId)
        {
            using var log = BeginFunction(nameof(DesignMicroService), nameof(GetDesignAsync), designSnapshotId);
            try
            {
                using var ctx = QuiltContextFactory.Create();

                //ctx.Database.Log = message => Trace.WriteLine(message);

                var dbDesignSnapshot = await ctx.DesignSnapshots.Where(r => r.DesignSnapshotId == designSnapshotId).SingleOrDefaultAsync().ConfigureAwait(false);

                if (dbDesignSnapshot == null)
                {
                    return(null);
                }

                //var ownerUserId = ParseUserId.FromOwnerReference(dbDesignSnapshot.Design.Owner.OwnerReference);
                //if (!SecurityPolicy.IsAuthorized(userId, ownerUserId))
                //{
                //    return null;
                //}

                //Logger.LogMessage("dbDesignSnapshot retrieved.");

                var result = Create.MDesign_Design(dbDesignSnapshot);

                log.Result(result);

                return(result);
            }
            catch (Exception ex)
            {
                log.Exception(ex);
                throw;
            }
        }
        public async Task SendEmailAsyncCore(string email, string subject, string htmlMessage)
        {
            using var ctx = QuiltContextFactory.Create();

            var dbEmailRequest = new EmailRequest()
            {
                EmailRequestStatusCode = EmailRequestStatusCodes.Posted,
                SenderEmail            = Constants.DoNotReplyEmail,
                SenderEmailName        = Constants.DoNotReplyEmailName,
                RecipientEmail         = email,
                RecipientEmailName     = email,
                RecipientParticipantId = null,
                Subject                       = subject,
                BodyText                      = htmlMessage,
                BodyHtml                      = htmlMessage,
                BodyTypeCode                  = EmailBodyTypes.Html,
                CreateDateTimeUtc             = GetUtcNow(),
                EmailRequestStatusDateTimeUtc = GetUtcNow()
            };

            _ = ctx.EmailRequests.Add(dbEmailRequest);

            _ = await ctx.SaveChangesAsync().ConfigureAwait(false);
        }
 protected QuiltContext CreateQuiltContext()
 {
     return(QuiltContextFactory.Create());
 }
Exemple #7
0
        public async Task <long> CreateEntryAsync(string sku, string inventoryItemTypeCode, string name, string collection, string manufacturer, int hue, int saturation, int value, IEnumerable <string> unitOfMeasureCodes, string pricingScheduleName, DateTime utcNow)
        {
            using var ctx = QuiltContextFactory.Create();

            var dbPricingSchedule = ctx.PricingSchedules.Where(r => r.Name == pricingScheduleName).Single();

            var dbCollectionTag = ctx.Tags.Where(r => r.TagTypeCode == TagTypeCodes.Collection && r.Value == collection).SingleOrDefault();

            if (dbCollectionTag == null)
            {
                dbCollectionTag = new Tag()
                {
                    TagTypeCodeNavigation = ctx.TagType(TagTypeCodes.Collection),
                    Value             = collection,
                    CreateDateTimeUtc = utcNow
                };
                _ = ctx.Tags.Add(dbCollectionTag);
            }

            var dbManufacturerTag = ctx.Tags.Where(r => r.TagTypeCode == TagTypeCodes.Manufacturer && r.Value == manufacturer).SingleOrDefault();

            if (dbManufacturerTag == null)
            {
                dbManufacturerTag = new Tag()
                {
                    TagTypeCodeNavigation = ctx.TagType(TagTypeCodes.Manufacturer),
                    Value             = manufacturer,
                    CreateDateTimeUtc = utcNow
                };
                _ = ctx.Tags.Add(dbManufacturerTag);
            }

            var dbInventoryItem = ctx.InventoryItems.Where(r => r.Sku == sku).SingleOrDefault();

            if (dbInventoryItem == null)
            {
                dbInventoryItem = new InventoryItem()
                {
                    Sku = sku,
                    InventoryItemTypeCode = inventoryItemTypeCode,
                    Name             = name,
                    Quantity         = 0,
                    ReservedQuantity = 0,
                    Hue             = hue,
                    Saturation      = saturation,
                    Value           = value,
                    PricingSchedule = dbPricingSchedule
                };
                _ = ctx.InventoryItems.Add(dbInventoryItem);
            }
            else
            {
                dbInventoryItem.InventoryItemTypeCode = inventoryItemTypeCode;
                dbInventoryItem.Name = name;
                //dbInventoryItem.Quantity
                //dbInventoryItem.ReservedQuantity
                dbInventoryItem.Hue             = hue;
                dbInventoryItem.Saturation      = saturation;
                dbInventoryItem.Value           = value;
                dbInventoryItem.PricingSchedule = dbPricingSchedule;
            }

            var dbInventoryItemCollectionTag = dbInventoryItem.InventoryItemTags.Where(r => r.Tag.TagTypeCode == TagTypeCodes.Collection).SingleOrDefault();

            if (dbInventoryItemCollectionTag == null)
            {
                dbInventoryItemCollectionTag = new InventoryItemTag()
                {
                    InventoryItem     = dbInventoryItem,
                    Tag               = dbCollectionTag,
                    CreateDateTimeUtc = utcNow,
                };
                _ = ctx.InventoryItemTags.Add(dbInventoryItemCollectionTag);
            }
            else
            {
                dbInventoryItemCollectionTag.Tag = dbCollectionTag;
            }

            var dbInventoryItemManufacturerTag = dbInventoryItem.InventoryItemTags.Where(r => r.Tag.TagTypeCode == TagTypeCodes.Manufacturer).SingleOrDefault();

            if (dbInventoryItemManufacturerTag == null)
            {
                dbInventoryItemManufacturerTag = new InventoryItemTag()
                {
                    InventoryItem     = dbInventoryItem,
                    Tag               = dbManufacturerTag,
                    CreateDateTimeUtc = utcNow
                };
                _ = ctx.InventoryItemTags.Add(dbInventoryItemManufacturerTag);
            }
            else
            {
                dbInventoryItemManufacturerTag.Tag = dbManufacturerTag;
            }

            foreach (var unitOfMeasureCode in unitOfMeasureCodes)
            {
                var dbUnitOfMeasure = ctx.UnitOfMeasure(unitOfMeasureCode);
                if (!dbInventoryItem.InventoryItemUnits.Any(r => r.UnitOfMeasureCode == unitOfMeasureCode))
                {
                    var dbInventoryItemUnit = new InventoryItemUnit()
                    {
                        InventoryItem = dbInventoryItem,
                        UnitOfMeasureCodeNavigation = dbUnitOfMeasure
                    };
                    _ = ctx.InventoryItemUnits.Add(dbInventoryItemUnit);
                }
            }

            _ = await ctx.SaveChangesAsync().ConfigureAwait(false);

            InvalidateCachedEntries();

            return(dbInventoryItem.InventoryItemId);
        }
Exemple #8
0
        private List <MInventory_LibraryEntry> LoadEntries()
        {
            //Logger.LogMessage("InventoryItemLibrary::LoadEntries");

            var entries = new List <MInventory_LibraryEntry>();

            using (var ctx = QuiltContextFactory.Create())
            {
                var dbInventoryItems = ctx.InventoryItems
                                       .Include(r => r.InventoryItemTypeCodeNavigation)
                                       .Include(r => r.InventoryItemStocks)
                                       .Include(r => r.InventoryItemTags)
                                       .ThenInclude(r => r.Tag)
                                       .Where(r => r.Quantity > 0)
                                       .OrderBy(r => r.Hue).ThenBy(r => r.Value).ThenBy(r => r.Saturation)
                                       .ToList();

                foreach (var dbInventoryItem in dbInventoryItems)
                {
                    var dbCollectionTag   = dbInventoryItem.InventoryItemTags.Where(r => r.Tag.TagTypeCode == TagTypeCodes.Collection).SingleOrDefault();
                    var dbManufacturerTag = dbInventoryItem.InventoryItemTags.Where(r => r.Tag.TagTypeCode == TagTypeCodes.Manufacturer).SingleOrDefault();

                    IList <MInventory_LibraryItemStockEntry> stocks = null;
                    foreach (var dbInventoryItemStock in dbInventoryItem.InventoryItemStocks)
                    {
                        if (stocks == null)
                        {
                            stocks = new List <MInventory_LibraryItemStockEntry>();
                        }

                        var stock = new MInventory_LibraryItemStockEntry(
                            dbInventoryItemStock.InventoryItemStockId,
                            dbInventoryItemStock.UnitOfMeasureCodeNavigation.Name,
                            dbInventoryItemStock.UnitCost,
                            dbInventoryItemStock.StockDateTimeUtc,
                            dbInventoryItemStock.OriginalQuantity,
                            dbInventoryItemStock.CurrentQuantity);

                        stocks.Add(stock);
                    }

                    var entry = new MInventory_LibraryEntry(
                        dbInventoryItem.InventoryItemId,
                        dbInventoryItem.Sku,
                        dbInventoryItem.Name,
                        dbInventoryItem.InventoryItemTypeCode,
                        dbInventoryItem.PricingScheduleId,
                        dbManufacturerTag?.Tag.Value,
                        dbCollectionTag?.Tag.Value,
                        dbInventoryItem.Quantity,
                        dbInventoryItem.ReservedQuantity,
                        dbInventoryItem.Hue,
                        dbInventoryItem.Saturation,
                        dbInventoryItem.Value,
                        stocks ?? EMPTY_STOCK_LIST);

                    entries.Add(entry);
                }
            }

            return(entries);
        }
        private async Task <long> SendMessageAsync(string sendReceiveCode, long participantId, string subject, string text, long?replyToMessageId, long?topicId)
        {
            using var ctx = QuiltContextFactory.Create();

            var dbParticipant = await ctx.Participants.Where(r => r.ParticipantId == participantId).FirstAsync().ConfigureAwait(false);

            string formattedName;
            string email;

            if (TryParseUserId.FromParticipantReference(dbParticipant.ParticipantReference, out string userId))
            {
                var dbAspNetUser = await ctx.AspNetUsers.Where(r => r.Id == userId).SingleAsync().ConfigureAwait(false);

                var dbUserProfile = await ctx.UserProfiles.Where(r => r.UserProfileAspNetUser.AspNetUserId == userId).SingleOrDefaultAsync().ConfigureAwait(false);

                formattedName = Create.FormattedName(dbUserProfile);
                email         = dbAspNetUser.Email;
            }
            else
            {
                formattedName = dbParticipant.ParticipantReference;
                email         = $"{dbParticipant.ParticipantId}@richtodd.com";
            }

            Message dbReplyToMessage;

            if (replyToMessageId != null)
            {
                dbReplyToMessage = await ctx.Messages.Where(r => r.MessageId == replyToMessageId.Value).SingleAsync().ConfigureAwait(false);

                if (dbReplyToMessage.ParticipantId != participantId)
                {
                    throw new InvalidOperationException(string.Format("Reply to message user ID mismatch (user ID = {0}, message user ID = {1}). ", participantId, dbReplyToMessage.Participant.ParticipantReference));
                }

                if (topicId == null)
                {
                    // Propagate order ID from original message.
                    //
                    topicId = dbReplyToMessage.TopicId;
                }
                else
                {
                    if (dbReplyToMessage.TopicId != null)
                    {
                        if (dbReplyToMessage.TopicId != topicId)
                        {
                            throw new InvalidOperationException(string.Format("Reply to message topic ID mismatch (topic ID = {0}, message topic ID = {1}). ", topicId, dbReplyToMessage.TopicId));
                        }
                    }
                }
            }
            else
            {
                dbReplyToMessage = null;
            }

            var dbMessage = new Message()
            {
                ParticipantId     = participantId,
                ConversationId    = dbReplyToMessage != null ? dbReplyToMessage.ConversationId : Guid.NewGuid(),
                SendReceiveCode   = sendReceiveCode,
                Subject           = subject,
                Text              = text,
                Email             = email,
                TopicId           = topicId,
                CreateDateTimeUtc = GetUtcNow()
            };

            _ = ctx.Messages.Add(dbMessage);

            IDictionary <string, string> topicFields = new Dictionary <string, string>();

            if (topicId.HasValue)
            {
                foreach (var dbTopicField in await ctx.TopicFields.Where(r => r.TopicId == topicId.Value).ToListAsync())
                {
                    topicFields[dbTopicField.FieldCode] = dbTopicField.FieldValue;
                }
            }

            var formatter = new InboundMessageEmailFormatter(formattedName, email, subject, text, topicFields);

            var dbEmailRequest = new EmailRequest()
            {
                EmailRequestStatusCode = EmailRequestStatusCodes.Posted,
                SenderEmail            = Constants.DoNotReplyEmail,     // dbAspNetUser.Email
                SenderEmailName        = Constants.DoNotReplyEmailName, // dbAspNetUser.EmailName
                RecipientEmail         = Constants.AdminMailEmail,
                RecipientEmailName     = Constants.AdminMailEmailName,
                RecipientParticipantId = null,
                Subject                       = formatter.GetSubject(),
                BodyText                      = formatter.GetText(),
                BodyHtml                      = formatter.GetHtml(),
                BodyTypeCode                  = EmailBodyTypes.Message,
                CreateDateTimeUtc             = GetUtcNow(),
                EmailRequestStatusDateTimeUtc = GetUtcNow()
            };

            _ = ctx.EmailRequests.Add(dbEmailRequest);

            var dbMessageEmailRequest = new MessageEmailRequest()
            {
                Message      = dbMessage,
                EmailRequest = dbEmailRequest
            };

            _ = ctx.MessageEmailRequests.Add(dbMessageEmailRequest);

            _ = await ctx.SaveChangesAsync().ConfigureAwait(false);

            return(dbMessage.MessageId);
        }
        private async Task TransmitPendingEmailAsync(long emailRequestId)
        {
            using var ctx = QuiltContextFactory.Create();

            var dbEmailRequest = await ctx.EmailRequests.Where(r => r.EmailRequestId == emailRequestId).SingleAsync().ConfigureAwait(false);

            if (dbEmailRequest.EmailRequestStatusCode != EmailRequestStatusCodes.Posted)
            {
                throw new BusinessOperationException(string.Format("Invalid email request status (ID = {0}, Status = {1}).", emailRequestId, dbEmailRequest.EmailRequestStatusCode));
            }

            var bodyType = dbEmailRequest.BodyTypeCode;
            var bodyText = dbEmailRequest.BodyText;
            var bodyHtml = dbEmailRequest.BodyHtml;

            switch (bodyType)
            {
            case EmailBodyTypes.Alert:
            {
                var dbAlertEmailRequest = dbEmailRequest.AlertEmailRequests.FirstOrDefault();
                if (dbAlertEmailRequest != null)
                {
                    bodyText = bodyText.Replace(TemplateVariables.DeferredAlertId, dbAlertEmailRequest.AlertId.ToString());
                    bodyHtml = bodyHtml.Replace(TemplateVariables.DeferredAlertId, dbAlertEmailRequest.AlertId.ToString());
                }
            }
            break;

            case EmailBodyTypes.Message:
            {
                var dbMessageEmailRequest = dbEmailRequest.MessageEmailRequests.FirstOrDefault();
                if (dbMessageEmailRequest != null)
                {
                    bodyText = bodyText.Replace(TemplateVariables.DeferredMessageId, dbMessageEmailRequest.MessageId.ToString());
                    bodyHtml = bodyHtml.Replace(TemplateVariables.DeferredMessageId, dbMessageEmailRequest.MessageId.ToString());
                }
            }
            break;

            case EmailBodyTypes.Notification:
            {
                var dbNotificationEmailRequest = dbEmailRequest.NotificationEmailRequests.FirstOrDefault();
                if (dbNotificationEmailRequest != null)
                {
                    bodyText = bodyText.Replace(TemplateVariables.DeferredNotificationId, dbNotificationEmailRequest.NotificationId.ToString());
                    bodyHtml = bodyHtml.Replace(TemplateVariables.DeferredNotificationId, dbNotificationEmailRequest.NotificationId.ToString());
                }
            }
            break;
            }

            var emailRequest = new ApplicationEmailRequest()
            {
                SenderEmail        = dbEmailRequest.SenderEmail,
                SenderEmailName    = dbEmailRequest.SenderEmailName,
                RecipientEmail     = dbEmailRequest.RecipientEmail,
                RecipientEmailName = dbEmailRequest.RecipientEmailName,
                Subject            = dbEmailRequest.Subject,
                BodyText           = bodyText,
                BodyHtml           = bodyHtml
            };

            await ApplicationEmailSender.SendEmailAsync(emailRequest);

            // Update the email request status.
            //
            dbEmailRequest.EmailRequestStatusCode        = EmailRequestStatusCodes.Complete;
            dbEmailRequest.EmailRequestStatusDateTimeUtc = GetUtcNow();

            _ = await ctx.SaveChangesAsync().ConfigureAwait(false);
        }
        public async Task SendNotification(long participantId, string notificationTypeCode, long?topicId)
        {
            using var log = BeginFunction(nameof(CommunicationMicroService), nameof(SendNotification), participantId, notificationTypeCode, topicId);
            try
            {
                using var ctx = QuiltContextFactory.Create();

                var dbNotification = new Notification()
                {
                    ParticipantId        = participantId,
                    NotificationTypeCode = notificationTypeCode,
                    TopicId           = topicId,
                    CreateDateTimeUtc = GetUtcNow()
                };
                _ = ctx.Notifications.Add(dbNotification);

                var dbNotificationType = ctx.NotificationTypes.Find(dbNotification.NotificationTypeCode);

                var formatter = new NotificationEmailFormatter(dbNotificationType.Subject);

                var dbParticipant = ctx.Participants.Where(r => r.ParticipantId == dbNotification.ParticipantId).Single();

                string email;
                if (TryParseUserId.FromParticipantReference(dbParticipant.ParticipantReference, out string userId))
                {
                    var dbAspNetUser = await ctx.AspNetUsers.Where(r => r.Id == userId).SingleAsync().ConfigureAwait(false);

                    email = dbAspNetUser.Email;

                    var dbEmailRequest = new EmailRequest()
                    {
                        EmailRequestStatusCode = EmailRequestStatusCodes.Posted,
                        SenderEmail            = Constants.DoNotReplyEmail,
                        SenderEmailName        = Constants.DoNotReplyEmailName,
                        RecipientEmail         = email,
                        RecipientEmailName     = email,
                        RecipientParticipant   = dbNotification.Participant,
                        Subject                       = formatter.GetSubject(),
                        BodyText                      = formatter.GetText(),
                        BodyHtml                      = formatter.GetHtml(),
                        BodyTypeCode                  = EmailBodyTypes.Notification,
                        CreateDateTimeUtc             = GetUtcNow(),
                        EmailRequestStatusDateTimeUtc = GetUtcNow(),
                    };
                    _ = ctx.EmailRequests.Add(dbEmailRequest);

                    var dbNotificationEmailRequest = new NotificationEmailRequest()
                    {
                        Notification = dbNotification,
                        EmailRequest = dbEmailRequest
                    };
                    _ = ctx.NotificationEmailRequests.Add(dbNotificationEmailRequest);
                }

                _ = await ctx.SaveChangesAsync().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                log.Exception(ex);
                throw;
            }
        }
        public async Task <MCommunication_MessageList> GetMessagesAsync(MCommunication_MessageMailbox mailbox, MCommunication_MessageStatus status, int recordCount, long?participantId)
        {
            using var log = BeginFunction(nameof(CommunicationMicroService), nameof(GetMessagesAsync), participantId, mailbox, status, recordCount);
            try
            {
                //AssertIsEndUser(userId);
                //await Assert(SecurityPolicy.IsAuthorized, userId).ConfigureAwait(false);

                using var ctx = QuiltContextFactory.Create();

                var query = (IQueryable <Message>)ctx.Messages;

                if (participantId != null)
                {
                    query = query.Where(r => r.ParticipantId == participantId);
                }

                switch (mailbox)
                {
                case MCommunication_MessageMailbox.ToUser:
                    query = query.Where(r => r.SendReceiveCode == SendReceiveCodes.ToUser);
                    break;

                case MCommunication_MessageMailbox.FromUser:
                    query = query.Where(r => r.SendReceiveCode == SendReceiveCodes.FromUser);
                    break;

                case MCommunication_MessageMailbox.MetaAll:
                    // No action required.
                    break;

                default:
                    throw new ArgumentException($"Unknown mailbox {mailbox}.");
                }

                switch (status)
                {
                case MCommunication_MessageStatus.Acknowledged:
                    query = query.Where(r => r.AcknowledgementDateTimeUtc != null);
                    break;

                case MCommunication_MessageStatus.Unacknowledged:
                    query = query.Where(r => r.AcknowledgementDateTimeUtc == null);
                    break;

                case MCommunication_MessageStatus.MetaAll:
                    // No action required.
                    break;

                default:
                    throw new ArgumentException($"Unknown status {status}.");
                }

                query = query.Take(recordCount);

                var messages = new List <MCommunication_Message>();
                foreach (var dbMessage in await query.ToListAsync().ConfigureAwait(false))
                {
                    var canAcknowledge = CanAcknowledge(dbMessage);

                    var message = Create.MCommunication_Message(ctx, dbMessage, canAcknowledge, false, null);
                    messages.Add(message);
                }

                var result = new MCommunication_MessageList()
                {
                    Messages = messages
                };

                log.Result(result);

                return(result);
            }
            catch (Exception ex)
            {
                log.Exception(ex);
                throw;
            }
        }
Exemple #13
0
        public async Task <Result> ExecuteAsync(string city, string postalCode, DateTime paymentDate)
        {
            using var log = BeginFunction(nameof(KansasSalesTaxTableLookupOperation), nameof(ExecuteAsync), city, postalCode, paymentDate);
            try
            {
                if (string.IsNullOrEmpty(city))
                {
                    throw new BusinessOperationException("Invalid city.");
                }
                if (string.IsNullOrEmpty(postalCode))
                {
                    throw new BusinessOperationException("Invalid postalCode");
                }
                if (postalCode.Length != 5 && postalCode.Length != 9)
                {
                    throw new BusinessOperationException("Invalid postalCode.");
                }

                // Table lookup ignores plus 4
                //
                if (postalCode.Length == 9)
                {
                    postalCode = postalCode.Substring(0, 5);
                }

                using (var ctx = QuiltContextFactory.Create())
                {
                    var taxTable = await ctx.KansasTaxTables.Where(r => paymentDate >= r.EffectiveDate && paymentDate < r.ExpirationDate).SingleOrDefaultAsync().ConfigureAwait(false);

                    if (taxTable == null)
                    {
                        throw new InvalidOperationException("Tax table not found for payment date.");
                    }

                    var taxTableEntry = taxTable.KansasTaxTableEntries.Where(r => r.PostalCode == postalCode && r.City == city).OrderByDescending(r => r.InsideCityTaxRate).FirstOrDefault();
                    if (taxTableEntry != null)
                    {
                        var result = new Result()
                        {
                            SalesTaxRate         = taxTableEntry.InsideCityTaxRate / 100m,
                            SalesTaxJurisdiction = taxTableEntry.InsideCityJurisdictionCode,
                            CityRate             = true
                        };

                        log.Result(result);
                        return(result);
                    }

                    taxTableEntry = taxTable.KansasTaxTableEntries.Where(r => r.PostalCode == postalCode).OrderByDescending(r => r.OutsideCityTaxRate).FirstOrDefault();
                    if (taxTableEntry != null)
                    {
                        var result = new Result()
                        {
                            SalesTaxRate         = taxTableEntry.OutsideCityTaxRate / 100m,
                            SalesTaxJurisdiction = taxTableEntry.OutsideCityJurisdictionCode,
                            CityRate             = false
                        };

                        log.Result(result);
                        return(result);
                    }
                }

                throw new InvalidOperationException("Salex tax record not found.");
            }
            catch (BusinessOperationException ex)
            {
                log.Exception(ex);
                throw;
            }
            catch (Exception ex)
            {
                log.Exception(ex);
                throw;
            }
        }
        public async Task <MDesign_FabricStyleCatalog> GetFabricStyles()
        {
            using var log = BeginFunction(nameof(DesignMicroService), nameof(GetFabricStyles));
            try
            {
                using var ctx = QuiltContextFactory.Create();

                var inventoryItems = await(from ii in ctx.InventoryItems
                                           where ii.InventoryItemTypeCode == InventoryItemTypeCodes.Fabric && (ii.Quantity - ii.ReservedQuantity) > 0
                                           orderby ii.Hue, ii.Saturation, ii.Value
                                           select ii).ToListAsync().ConfigureAwait(false);

                var tags = await(from iit in ctx.InventoryItemTags
                                 join t in ctx.Tags on iit.TagId equals t.TagId
                                 select new { iit.InventoryItemId, t.TagTypeCode, t.Value }).ToListAsync().ConfigureAwait(false);

                var manufacturerNames  = new Dictionary <long, string>();
                var collectionNameSets = new Dictionary <long, List <string> >();
                foreach (var tag in tags)
                {
                    var inventoryItem = inventoryItems.Where(ii => ii.InventoryItemId == tag.InventoryItemId).SingleOrDefault();
                    if (inventoryItem != null)
                    {
                        // Note: assumes an inventory item is associated with only one manufacturer.
                        //
                        if (tag.TagTypeCode == TagTypeCodes.Manufacturer)
                        {
                            manufacturerNames[tag.InventoryItemId] = tag.Value;
                        }

                        if (tag.TagTypeCode == TagTypeCodes.Collection)
                        {
                            if (!collectionNameSets.TryGetValue(tag.InventoryItemId, out var collectionNameSet))
                            {
                                collectionNameSet = new List <string>();
                                collectionNameSets[tag.InventoryItemId] = collectionNameSet;
                            }
                            collectionNameSet.Add(tag.Value);
                        }
                    }
                }

                var manufacturers  = new Dictionary <string, MDesign_FabricStyleManufacturer>();
                var collectionSets = new Dictionary <MDesign_FabricStyleManufacturer, List <MDesign_FabricStyleCollection> >();
                var fabricSets     = new Dictionary <MDesign_FabricStyleCollection, List <MDesign_FabricStyle> >();

                foreach (var inventoryItem in inventoryItems)
                {
                    var manufacturerName  = manufacturerNames[inventoryItem.InventoryItemId];
                    var collectionNameSet = collectionNameSets[inventoryItem.InventoryItemId];

                    if (!manufacturers.TryGetValue(manufacturerName, out var manufacturer))
                    {
                        manufacturer = new MDesign_FabricStyleManufacturer()
                        {
                            ManufacturerName = manufacturerName
                        };
                        manufacturers[manufacturerName] = manufacturer;

                        collectionSets[manufacturer] = new List <MDesign_FabricStyleCollection>();
                    }

                    var collectionSet = collectionSets[manufacturer];
                    foreach (var collectionName in collectionNameSet)
                    {
                        var collection = collectionSet.Where(r => r.CollectionName == collectionName).SingleOrDefault();
                        if (collection == null)
                        {
                            collection = new MDesign_FabricStyleCollection()
                            {
                                CollectionName = collectionName
                            };
                            collectionSet.Add(collection);

                            fabricSets[collection] = new List <MDesign_FabricStyle>();
                        }

                        var fabricSet   = fabricSets[collection];
                        var color       = Color.FromAhsb(255, inventoryItem.Hue, inventoryItem.Saturation / 100.0, inventoryItem.Value / 100.0);
                        var fabricStyle = new FabricStyle(inventoryItem.Sku, color);
                        fabricSet.Add(Create.MDesign_FabricStyle(fabricStyle));
                    }
                }

                foreach (var collection in fabricSets.Keys)
                {
                    collection.FabricStyles = fabricSets[collection].ToArray();
                }
                foreach (var manufacturer in collectionSets.Keys)
                {
                    manufacturer.Collections = collectionSets[manufacturer].ToArray();
                }

                var result = new MDesign_FabricStyleCatalog()
                {
                    Manufacturers = manufacturers.Values.ToArray()
                };

                log.Result(result);

                return(result);
            }
            catch (Exception ex)
            {
                log.Exception(ex);
                throw;
            }
        }
        public async Task <Guid> CreateDesignAsync(long ownerId, string name, MDesign_DesignSpecification designSpecification, DateTime utcNow)
        {
            using var log = BeginFunction(nameof(DesignMicroService), nameof(CreateDesignAsync), ownerId, name, designSpecification, utcNow);
            try
            {
                //if (SecurityPolicy.IsBuiltInUser(userId))
                //{
                //    throw new InvalidOperationException("Built-in user ID not supported.");
                //}

                //var artifactValue = design.JsonSave().ToString();

                using var ctx = QuiltContextFactory.Create();

                //var ownerReference = CreateOwnerReference.FromUserId(userId);
                //var dbOwner = await ctx.Owners.Where(r => r.OwnerReference == ownerReference).SingleOrDefaultAsync().ConfigureAwait(false);
                //if (dbOwner == null)
                //{
                //    dbOwner = new Owner()
                //    {
                //        OwnerReference = ownerReference,
                //        OwnerTypeCode = "A"
                //    };
                //    _ = ctx.Owners.Add(dbOwner);
                //}

                //ctx.Database.Log = message => Trace.WriteLine(message);

                var dbDesign = new QuiltSystem.Database.Model.Design()
                {
                    DesignId = Guid.NewGuid(),
                    OwnerId  = ownerId,
                    Name     = name ?? "New Project",
                    CurrentDesignSnapshotSequence = 0,
                    CreateDateTimeUtc             = utcNow,
                    UpdateDateTimeUtc             = utcNow
                };
                _ = ctx.Designs.Add(dbDesign);

                var dbArtifact = new Artifact()
                {
                    ArtifactTypeCode      = ArtifactTypeCodes.Design,
                    ArtifactValueTypeCode = ArtifactValueTypeCodes.Json,
                    Value = designSpecification.ArtifactValue
                };
                _ = ctx.Artifacts.Add(dbArtifact);

                var dbDesignSnapshot = new DesignSnapshot()
                {
                    Design = dbDesign,
                    DesignSnapshotSequence = 0,
                    Artifact          = dbArtifact,
                    Name              = name ?? "New Project",
                    CreateDateTimeUtc = utcNow,
                    UpdateDateTimeUtc = utcNow
                };
                _ = ctx.DesignSnapshots.Add(dbDesignSnapshot);

                _ = await ctx.SaveChangesAsync().ConfigureAwait(false);

                var result = dbDesign.DesignId;

                log.Result(result);

                return(result);
            }
            catch (Exception ex)
            {
                log.Exception(ex);
                throw;
            }
        }