Configure routing to explicitly allow anonymous access to the
PublicBots controller routes before the main admin routes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add [Route] and [HttpGet] attributes to ensure proper route discovery
and matching for anonymous ShareCard access.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created PublicBotsController with [AllowAnonymous] at class level
to avoid policy authorization conflicts with the main BotsController
- Updated ShareCard.cshtml to use PublicBots controller for embed links
- Fixes HTTP 500 error when accessing ShareCard without authentication
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add ShareCardEmbed.cshtml for embeddable public share card
- Add local qrcode.min.js (removed CDN dependency)
- Fix QR code generation by properly attaching canvas to DOM
- Add embed code modal with iframe and direct link copy buttons
- Use Url.Action() for proper URL generation
- Add bot discovery status migration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Gitea Actions workflow for manual AlexHost deployment
- Add docker-compose.alexhost.yml for production deployment
- Add deploy-alexhost.sh script with server-side build support
- Add Bot Control feature (Start/Stop/Restart) for remote bot management
- Add discovery control endpoint in TeleBot
- Update TeleBot with StartPollingAsync/StopPolling/RestartPollingAsync
- Fix platform architecture issues by building on target server
- Update docker-compose configurations for all environments
Deployment tested successfully:
- TeleShop: healthy at https://teleshop.silentmary.mywire.org
- TeleBot: healthy with discovery integration
- SilverPay: connectivity verified
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The original migration only added columns to Products table but never
created the VariantCollections and SalesLedgers tables, causing HTTP 500
errors on Products/Create page.
- Added CREATE TABLE IF NOT EXISTS for VariantCollections
- Added CREATE TABLE IF NOT EXISTS for SalesLedgers
- Added proper indexes for both tables
- Changed to raw SQL for idempotency (safe to re-run)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add ShareCard action to BotsController for generating bot share page
- Create ShareCard.cshtml view with gradient card design
- Generate QR code for Telegram bot link using QRCode.js
- Display bot info including type, status, description, and version
- Add copy link and print card functionality
- Add Share Bot button to bot Details page
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add LittleShopSessionId and MessageCount properties to UserSession model
- Integrate SessionManager with BotManagerService for remote session tracking
- Wire up SessionManager.SetBotManagerService() at startup in Program.cs
- Create remote sessions via BotManagerService.StartSessionAsync() when users connect
- Update remote sessions periodically (every 10 messages) via UpdateSessionAsync()
- Fix live activity feed to show newest records at top by reversing array iteration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The UpdateBotDiscoveryStatus method was a stub that only logged but never
saved the RemoteAddress, RemotePort, DiscoveryStatus, and RemoteInstanceId
to the database. Now it properly calls UpdateRemoteInfoAsync.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added connection string display to System Information section of dashboard.
- Injected IConfiguration into DashboardController
- Added ConnectionString to ViewData
- Displayed in monospace code format for easy reading
- Shows actual runtime connection string from configuration
- Helps verify which database file is being used in different environments
This makes it easier to troubleshoot database location issues, especially
when deploying to different environments (Development, Production, CT109, etc.).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Sample data (products, categories, orders) now only seeds in Development
- Production environment will start with empty database (admin user only)
- Ensures clean state for testing without pre-populated data
This allows production deployments to start with a truly empty database
for testing purposes, while development still gets sample data for
local testing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added VariantCollectionId and VariantsJson columns to Products table
- Migration was previously empty causing schema mismatch on startup
- Fixes "SQLite Error 1: 'no such column: p.VariantCollectionId'"
The migration file was scaffolded but never implemented, causing production
deployments to fail with database schema errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added @Html.AntiForgeryToken() to Customer.cshtml reply form
- Fixes HTTP 400 error when replying to customer messages
- Required for CSRF protection with [ValidateAntiForgeryToken]
The form was missing the CSRF token which caused ASP.NET Core to reject
all POST requests to /Admin/Messages/Reply with HTTP 400 status.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Modified OrdersController to include Processing (legacy) status in pending tab
- Updated badge count to include Processing orders in PendingPaymentCount
- Added database reset script that preserves bot tokens and integrations
Processing status (OrderStatus=20) is a legacy unpaid status that should be visible
in the Pending Payment workflow to allow staff to retry failed payment creation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed BotService to prevent duplicate bot registrations by checking for existing bot with same name/type
- Updated existing bot record instead of creating duplicates on re-registration
- Configured SilverPay integration with production API key
- Updated TeleBot configuration for local development (localhost API URL, Tor disabled)
This ensures single bot instances and proper payment gateway integration for testing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Test Infrastructure Improvements:
- Added missing service registrations to TestWebApplicationFactory
- ICryptoPaymentService
- IDataSeederService
- Fixed JWT configuration validation to skip in Testing environment
- Allow test environment to use default test JWT key
Impact:
- Test pass rate improved from 56/110 (51%) to 86/110 (78%)
- Fixed 30 integration and security test failures
- All catalog and most order controller tests now passing
Remaining Failures (24 tests):
- OrdersWithVariants tests (5) - Requires variant test data seeding
- OrdersController tests (5) - Requires product/category test data
- AuthenticationEnforcement tests (2) - Auth configuration issues
- UI/AdminPanel tests (12) - Playwright server configuration needed
Next Steps:
- Add test data seeding for product variants and multi-buy
- Configure Playwright tests to use TestWebApplicationFactory server
- Review authentication test expectations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major Feature Additions:
- Customer management: Full CRUD with data export and privacy compliance
- Payment management: Centralized payment tracking and administration
- Push notification subscriptions: Manage and track web push subscriptions
Security Enhancements:
- IP whitelist middleware for administrative endpoints
- Data retention service with configurable policies
- Enhanced push notification security documentation
- Security fixes progress tracking (2025-11-14)
UI/UX Improvements:
- Enhanced navigation with improved mobile responsiveness
- Updated admin dashboard with order status counts
- Improved product CRUD forms
- New customer and payment management interfaces
Backend Improvements:
- Extended customer service with data export capabilities
- Enhanced order service with status count queries
- Improved crypto payment service with better error handling
- Updated validators and configuration
Documentation:
- DEPLOYMENT_NGINX_GUIDE.md: Nginx deployment instructions
- IP_STORAGE_ANALYSIS.md: IP storage security analysis
- PUSH_NOTIFICATION_SECURITY.md: Push notification security guide
- UI_UX_IMPROVEMENT_PLAN.md: Planned UI/UX enhancements
- UI_UX_IMPROVEMENTS_COMPLETED.md: Completed improvements
Cleanup:
- Removed temporary database WAL files
- Removed stale commit message file
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: Variant editor was skipping ALL columns with headers starting with 'Property '
(e.g., 'Property 1'), which caused complete data loss during serialization.
When users entered data but didn't rename the default column header, serializeToJSON()
would skip the column entirely, returning an empty array [] to the database.
Fix: Only skip columns with truly empty names, not default 'Property X' names.
Users can now save data even if they haven't renamed column headers.
Files changed:
- wwwroot/js/variant-editor.js: Removed propertyName.startsWith('Property ') check
- Areas/Admin/Views/VariantCollections/Create.cshtml: Updated cache-busting to v=20251113d
- Areas/Admin/Views/VariantCollections/Edit.cshtml: Updated cache-busting to v=20251113d
Major UX improvements based on user feedback:
- Replaced auto-populated columns with preset shortcut buttons
- Quick Add buttons for Size, Color, Material, Storage
- Custom button for user-defined property names
- Double-click column headers to rename
- Rename column option in context menu
- Starts with single empty column instead of defaults
- Improved usage instructions in UI
- Cache-busting version updated to force reload
This design is more flexible and less confusing than auto-generating columns.
Added comprehensive mobile card layout for Products/Index, completing Phase 2 responsive design.
**Products Mobile View Features:**
- Horizontal layout with 80x80px product image on left
- Product name, category badge, price, and status on right
- Full description (100 chars) below header
- 2-column grid for Stock and Weight info
- Conditional badges for multi-buys and variants
- Full-width "View Details & Edit" button
**Mobile UX Highlights:**
- Larger product images (80px vs 50px desktop thumbnail)
- Price prominently displayed in green (fs-5)
- Stock status color-coded (success/warning)
- Variations clearly shown with icon badges
- Touch-friendly full-width action button
**Technical Implementation:**
- d-flex for image + info horizontal layout
- flex-grow-1 for responsive info section
- row g-2 for 2-column grid with gutters
- Conditional rendering for variations badges
- ARIA labels for accessibility
**Phase 2 Now Complete:**
✅ Categories - Simple cards with description
✅ Users - Minimal cards with user info
✅ ShippingRates - 2x2 grid for rate details
✅ VariantCollections - Cards with JSON preview
✅ Products - Rich cards with images and variations
✅ Orders - Mobile cards (already implemented)
All main Index views now mobile-optimized!
🚀 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented responsive mobile card layouts for all main Index views, providing superior mobile UX while maintaining desktop table views.
**Responsive Design Pattern:**
- Desktop (≥992px): Table layout with all data columns
- Mobile (<992px): Card-based layout optimized for touch interaction
- Breakpoint: Bootstrap's lg breakpoint for optimal viewing experience
**Views Converted:**
1. **Categories/Index.cshtml:**
- Mobile cards with name, description, product count, status
- Full-width action buttons for easy touch interaction
- Clear visual hierarchy with icons and badges
2. **Users/Index.cshtml:**
- Simplified mobile cards showing username, created date, status
- Conditional delete button (protected admin account)
- Clean, minimal design for quick user management
3. **ShippingRates/Index.cshtml:**
- 2x2 grid layout for shipping rate data (country, price, weight, delivery)
- Visual separation with light background boxes
- All critical information displayed in scannable format
4. **VariantCollections/Index.cshtml:**
- Properties JSON displayed in scrollable code block
- Created/Updated dates in compact format
- Clear deactivation action for variant collections
**Mobile UX Enhancements:**
- ✅ 44px minimum touch targets (Bootstrap .btn default)
- ✅ Full-width buttons with .d-grid gap-2 for easy tapping
- ✅ Proper spacing with mb-3 between cards
- ✅ Clear visual hierarchy with card-title and badges
- ✅ Descriptive button text (not just icons) on mobile
- ✅ Responsive icons and status indicators
- ✅ Word-break handling for long JSON strings
**Technical Implementation:**
- Used Bootstrap's d-none d-lg-block for desktop tables
- Used d-lg-none for mobile card views
- No JavaScript required - pure CSS responsive design
- Maintains all functionality from desktop view
- Zero data loss in mobile transformation
**Accessibility Maintained:**
- All ARIA labels preserved from Phase 1
- Semantic HTML structure in both views
- Proper heading hierarchy maintained
- Keyboard navigation fully functional
🚀 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented comprehensive accessibility enhancements to meet WCAG 2.1 AA standards:
**Skip Navigation:**
- Added skip-to-content link for keyboard users
- Link appears on focus and jumps directly to main content area
**Screen Reader Support:**
- Created .sr-only and .sr-only-focusable utility classes
- Added aria-hidden="true" to all decorative icons
- Added descriptive aria-label attributes to all icon-only buttons
**Enhanced Focus Indicators:**
- Implemented 3px visible outlines on all interactive elements
- Added :focus-visible for keyboard-only focus indicators
- Special focus styling for primary actions (orange outline)
- Consistent 2px outline-offset for better visibility
**Table Accessibility:**
- Added scope="col" attributes to all table headers
- Properly grouped button actions with role="group" and aria-label
**Button Improvements:**
- All icon-only buttons now have descriptive ARIA labels
- Added responsive text labels (visible on sm+ screens, hidden on mobile)
- Improved button groups with proper ARIA roles
**Files Modified:**
- _Layout.cshtml: Skip link, accessible menu close button
- Categories/Index.cshtml: ARIA labels, table scopes
- Users/Index.cshtml: ARIA labels, table scopes
- Orders/Index.cshtml: Table scopes
- Products/Index.cshtml: Table scopes
- ShippingRates/Index.cshtml: ARIA labels, table scopes
- VariantCollections/Index.cshtml: ARIA labels, table scopes
- modern-admin.css: Accessibility utilities and enhanced focus styles
**WCAG 2.1 AA Criteria Addressed:**
- 2.4.1 Bypass Blocks (Level A)
- 2.4.7 Focus Visible (Level AA)
- 4.1.2 Name, Role, Value (Level A)
- 1.3.1 Info and Relationships (Level A)
🚀 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Changed JSON naming policy from CamelCase to SnakeCaseLower for SilverPay API compatibility
- Fixed field name from 'fiat_amount' to 'amount' in request body
- Used unique payment ID instead of order ID to avoid duplicate external_id conflicts
- Modified SilverPayApiResponse to handle string amounts from API
- Added [JsonIgnore] attributes to computed properties to prevent JSON serialization conflicts
- Fixed test compilation errors (mock service and enum casting issues)
- Updated SilverPay endpoint to http://10.0.0.52:8001/🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL BUG FIX: Orders were totaling £0 because imported products had:
- Base price set to £0
- Variants stored as ProductMultiBuys (not ProductVariants)
- Order creation couldn't find variant prices → used base price of £0
Changes:
- CSV import now detects format: semicolons (;) = variants, colons (:) = multi-buys
- Added ImportProductVariantsAsync() to handle pipe-delimited variant format
- Format: "value; price; stock|value; price; stock" (e.g., "10; 30.00; 100|25; 70.00; 50")
- Updated CSV export to prioritize ProductVariants over MultiBuys
- Updated CSV template with correct variant format examples
- Added comprehensive documentation in VARIANT_CSV_FORMAT.md
Migration Required:
- Existing products with incorrect MultiBuy data need re-import
- Convert format from "name:qty:price;name:qty:price" to "value; price; stock|value; price; stock"
- Ensure base price is 0 for variant-based products
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Previous Approach (WRONG):**
- Created a separate table section to display ProductVariants
- User wanted data in the EXISTING collapsible panels, not a new section
**Proper Fix:**
- ProductImportService creates records in ProductVariants table
- Edit page's collapsible panels read from VariantsJson field (different system)
- Solution: Convert ProductVariants → VariantsJson format on page load
**Changes:**
1. **ProductsController.cs (Lines 105-115):**
- Load ProductVariants from database
- If VariantsJson empty but ProductVariants exist, convert them
- Format: `[{Weight: "28g", Price: 700, StockQty: 100}, ...]`
- JavaScript reads Price and StockQty to populate collapsible panel fields
2. **Edit.cshtml:**
- Removed the extra table section
- Existing collapsible panels now display imported data automatically
**Result:**
When you open Edit page, expand "Product Variants" → "Price, Stock & Weight Details",
the fields will be PRE-FILLED with your imported values (700, 100, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
- Variant price overrides and stock quantities were hidden in collapsible
panels in the Product Edit page
- The Edit page was showing the VariantCollections system (VariantsJson)
instead of the actual ProductVariant records created by text import
- User had to expand each variant panel to see price and stock values
**Solution:**
1. **ProductsController.cs (Lines 101-103):**
- Added call to GetProductVariantsAsync() to load actual variant records
- Added ViewData["ProductVariants"] to pass data to view
2. **Edit.cshtml (Lines 320-413):**
- Added new collapsible section "Product Variants"
- Displays variants in a table with directly visible columns:
* Name, Type, Price, Stock Level, Sort Order, Status
- No hidden panels - all information visible at a glance
- Added quick summary with total variants, stock, and price range
- Includes helpful links to ProductVariants management page
**Technical Details:**
- Price displays in green with £ symbol when override exists
- Stock shows color-coded badges (green=in stock, red=out of stock)
- Section only appears if variants exist (conditional rendering)
- Expanded by default (aria-expanded="true") for immediate visibility
**Impact:**
- User can now see all variant prices and stock quantities immediately
- No need to click/expand individual variant panels
- Better UX for products imported via text import format
- Maintains separation between VariantCollections system and ProductVariants
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added detailed logging to ParseAndImportVariantLine to output:
- Variant name/value
- Price override
- Stock quantity
- Variant type
This will help diagnose why variant price and stock aren't showing up
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add replaceAll checkbox to ImportText view with warning
- Pass replaceAll parameter to import service
- Allows complete product catalog replacement via text import
- Enhanced documentation for unit types and variant collections
- Fix optimistic concurrency errors in product import by using ExecuteSqlRaw instead of EF tracking
- Add DeleteAllOrdersAndSalesDataAsync() method to clear orders, payments, customers, and messages
- Add DeleteAllSalesData endpoint to ProductsController for admin access
- Proper deletion order to avoid foreign key violations
- Enhanced logging for troubleshooting data cleanup operations
Resolves: Import errors with 'database operation expected to affect 1 row(s)'
- Added Replace All checkbox to import UI for clean slate imports
- Implemented DeleteAllProductsAndCategoriesAsync for complete data wipe
- Added auto-creation of categories during CSV import
- Created products_import.csv with 13 products across 4 categories
- Added comprehensive IMPORT_INSTRUCTIONS.md documentation
Technical changes:
- ProductImportService: Added replaceAll parameter to all import methods
- ProductImportService: Categories now auto-created if missing from CSV
- ProductsController: Added replaceAll parameter to Import action
- Import.cshtml: Added Replace All checkbox with danger warnings
Categories: Flour, Cereal, Vitamins, Herbal
Products: 13 products with full variant pricing structures
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created NotificationHub for instant browser notifications
- Updated CryptoPaymentService to broadcast via SignalR
- Added JavaScript client with toast notifications
- Works with custom SSL certificates (no FCM dependency)
- Automatic reconnection with exponential backoff
- Notification sound and visual indicators
- Bypasses all Web Push SSL certificate issues
TeleBot Configuration:
- Added TeleBot API URL and API key to docker-compose.yml
- Configured to connect to telebot-service:5000 internally
- Enables customer notifications via Telegram bot
Expired Payment Handling:
- Auto-cancel orders when payment status is Expired
- Only cancels orders in PendingPayment status
- Logs cancellation for audit trail
Customer View Improvements:
- Hide cancelled orders from customer order lists
- Filters applied to both GetOrdersByIdentityAsync and GetOrdersByCustomerIdAsync
- Prevents confusion from displaying cancelled/expired orders
This resolves:
- No notifications to customers (TeleBot not configured)
- No notifications to admin (TeleBot connection failed)
- Expired orders remaining visible to customers
- Orders not auto-cancelled when payment expires
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Webhook Improvements:
- Added Confirmations field to PaymentWebhookDto (default: 0)
- Updated webhook controller to pass confirmations to service layer
- Fixed notification logic to match order update conditions
Payment Confirmation Logic:
- Paid (2): Confirmed immediately regardless of confirmations
- Overpaid (3): Confirmed immediately regardless of confirmations
- Completed (7): Requires 3+ blockchain confirmations
- Notifications only sent when order is actually updated
This prevents premature notifications for unconfirmed 'Completed' status
while maintaining immediate processing for 'Paid' and 'Overpaid' statuses.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added quick action button on Packing tab to dispatch orders
- Created dispatch modal with tracking number input
- Modal includes tracking number, estimated days, and notes fields
- Button appears on both desktop table and mobile card views
- Fixes workflow gap where Packing orders had no quick action
- Orders now properly flow: Accepted → Packing → Dispatched
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added PaymentStatus.Overpaid to notification trigger conditions
- Overpaid payments now update order status to PaymentReceived
- Overpaid payments now send admin push notifications
- Overpaid payments now send TeleBot customer notifications
- Resolves issue where successful overpayments were silent
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>