Add customer communication system

This commit is contained in:
sysadmin
2025-08-27 18:02:39 +01:00
parent 1f7c0af497
commit eae5be3e7c
136 changed files with 14552 additions and 97 deletions

View File

@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace TeleBot.Models
{
public class ShoppingCart
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public List<CartItem> Items { get; set; } = new();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
public void AddItem(Guid productId, string productName, decimal price, int quantity = 1)
{
var existingItem = Items.FirstOrDefault(i => i.ProductId == productId);
if (existingItem != null)
{
existingItem.Quantity += quantity;
existingItem.UpdateTotalPrice();
}
else
{
var newItem = new CartItem
{
ProductId = productId,
ProductName = productName,
UnitPrice = price,
Quantity = quantity
};
newItem.UpdateTotalPrice(); // Ensure total is calculated after all properties are set
Items.Add(newItem);
}
UpdatedAt = DateTime.UtcNow;
}
public void RemoveItem(Guid productId)
{
Items.RemoveAll(i => i.ProductId == productId);
UpdatedAt = DateTime.UtcNow;
}
public void UpdateQuantity(Guid productId, int quantity)
{
var item = Items.FirstOrDefault(i => i.ProductId == productId);
if (item != null)
{
if (quantity <= 0)
{
RemoveItem(productId);
}
else
{
item.Quantity = quantity;
item.UpdateTotalPrice();
UpdatedAt = DateTime.UtcNow;
}
}
}
public void Clear()
{
Items.Clear();
UpdatedAt = DateTime.UtcNow;
}
public decimal GetTotalAmount()
{
return Items.Sum(i => i.TotalPrice);
}
public int GetTotalItems()
{
return Items.Sum(i => i.Quantity);
}
public bool IsEmpty()
{
return !Items.Any();
}
}
public class CartItem
{
public Guid ProductId { get; set; }
public string ProductName { get; set; } = string.Empty;
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal TotalPrice { get; set; }
public CartItem()
{
// Don't calculate total in constructor - wait for properties to be set
}
public void UpdateTotalPrice()
{
TotalPrice = UnitPrice * Quantity;
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
namespace TeleBot.Models
{
public class UserSession
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public string HashedUserId { get; set; } = string.Empty;
public SessionState State { get; set; } = SessionState.MainMenu;
// Telegram User Information (for customer creation)
public long TelegramUserId { get; set; }
public string TelegramUsername { get; set; } = string.Empty;
public string TelegramDisplayName { get; set; } = string.Empty;
public string TelegramFirstName { get; set; } = string.Empty;
public string TelegramLastName { get; set; } = string.Empty;
public ShoppingCart Cart { get; set; } = new();
public Dictionary<string, object> TempData { get; set; } = new();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime LastActivityAt { get; set; } = DateTime.UtcNow;
public DateTime ExpiresAt { get; set; }
public bool IsEphemeral { get; set; } = true;
public PrivacySettings Privacy { get; set; } = new();
// Order flow data (temporary)
public OrderFlowData? OrderFlow { get; set; }
public static string HashUserId(long telegramUserId, string salt = "TeleBot-Privacy-Salt")
{
using var sha256 = SHA256.Create();
var bytes = Encoding.UTF8.GetBytes($"{telegramUserId}:{salt}");
var hash = sha256.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
public bool IsExpired()
{
return DateTime.UtcNow > ExpiresAt;
}
public void UpdateActivity()
{
LastActivityAt = DateTime.UtcNow;
}
}
public class PrivacySettings
{
public bool UseEphemeralMode { get; set; } = true;
public bool UseTorOnly { get; set; } = false;
public bool DisableAnalytics { get; set; } = true;
public bool RequirePGP { get; set; } = false;
public string? PGPPublicKey { get; set; }
public bool EnableDisappearingMessages { get; set; } = true;
public int DisappearingMessageTTL { get; set; } = 30; // seconds
}
public class OrderFlowData
{
public string? IdentityReference { get; set; }
public string? ShippingName { get; set; }
public string? ShippingAddress { get; set; }
public string? ShippingCity { get; set; }
public string? ShippingPostCode { get; set; }
public string? ShippingCountry { get; set; } = "United Kingdom";
public string? Notes { get; set; }
public string? SelectedCurrency { get; set; }
public bool UsePGPEncryption { get; set; }
public OrderFlowStep CurrentStep { get; set; } = OrderFlowStep.CollectingName;
}
public enum OrderFlowStep
{
CollectingName,
CollectingAddress,
CollectingCity,
CollectingPostCode,
CollectingCountry,
CollectingNotes,
ReviewingOrder,
SelectingPaymentMethod,
ProcessingPayment,
Complete
}
public enum SessionState
{
MainMenu,
BrowsingCategories,
ViewingProducts,
ViewingProduct,
ViewingCart,
CheckoutFlow,
ViewingOrders,
ViewingOrder,
PrivacySettings,
Help
}
}