Skip to content

Commit 1ccad0d

Browse files
committed
feat: Add WhatsApp Webhook Event handling and OpenWA client integration
- Created migration for WhatsAppWebhookEvents table to store incoming webhook events. - Implemented WhatsAppWebhookEventEntity model for ORM mapping. - Developed IOpenWAClient interface for OpenWA API interactions. - Implemented OpenWAClient class to handle HTTP requests to the OpenWA gateway. - Added OpenWAGatewayException for error handling during API calls. - Created PowerShell scripts for managing OpenWA startup on Windows, including installation, registration, and removal of scheduled tasks. - Documented OpenWA Windows startup procedures in a new markdown file.
1 parent 3095643 commit 1ccad0d

78 files changed

Lines changed: 12072 additions & 347 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

OpenWA

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 697b4a199f6093ff9b0b7d146bacd970d53c421a

ShopInventory.Web/Components/Layout/NavMenu.razor

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,12 @@
801801
</span>
802802
<span class="snav-text">Webhooks</span>
803803
</NavLink>
804+
<NavLink class="snav-link" href="/whatsapp-inbox" Match="NavLinkMatch.Prefix">
805+
<span class="snav-icon">
806+
<MudIcon Icon="@Icons.Material.Filled.Chat" />
807+
</span>
808+
<span class="snav-text">WhatsApp Inbox</span>
809+
</NavLink>
804810
<NavLink class="snav-link" href="/swagger" Match="NavLinkMatch.Prefix">
805811
<span class="snav-icon">
806812
<MudIcon Icon="@Icons.Material.Filled.Api" />

ShopInventory.Web/Components/Pages/MobileDrafts.razor

Lines changed: 256 additions & 20 deletions
Large diffs are not rendered by default.

ShopInventory.Web/Components/Pages/PodUploadReport.razor

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
@BasePendingCount pending
4444
</span>
4545
<MudButton Variant="Variant.Outlined" Color="Color.Default" OnClick="ExportToExcel"
46-
Disabled="@(isExporting || FilteredCount == 0)" Class="podr-export-btn">
46+
Disabled="@(isExporting || BaseFilteredCount == 0)" Class="podr-export-btn">
4747
@if (isExporting)
4848
{
4949
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="me-1" />
@@ -1002,19 +1002,20 @@
10021002

10031003
private async Task ExportToExcel()
10041004
{
1005-
if (report == null || FilteredCount == 0) return;
1005+
if (report == null || BaseFilteredCount == 0) return;
10061006
isExporting = true;
10071007
StateHasChanged();
10081008
try
10091009
{
1010+
var exportItems = BaseFilteredItems.ToList();
10101011
var exportReport = new PodUploadStatusReport
10111012
{
10121013
FromDate = report.FromDate,
10131014
ToDate = report.ToDate,
1014-
TotalInvoices = FilteredCount,
1015-
UploadedCount = FilteredItems.Count(i => i.HasPod),
1016-
PendingCount = FilteredItems.Count(i => !i.HasPod),
1017-
Items = FilteredItems.ToList()
1015+
TotalInvoices = exportItems.Count,
1016+
UploadedCount = exportItems.Count(i => i.HasPod),
1017+
PendingCount = exportItems.Count(i => !i.HasPod),
1018+
Items = exportItems
10181019
};
10191020

10201021
var bytes = ExportService.ExportPodUploadStatusToExcel(exportReport);

ShopInventory.Web/Components/Pages/ProofOfDelivery.razor

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@page "/pods"
2+
@using System.Globalization
23
@using Microsoft.AspNetCore.Authorization
34
@using ShopInventory.Web.Common
45
@using ShopInventory.Web.Models
@@ -1387,19 +1388,91 @@
13871388
private bool deleteSuccess;
13881389
private PodAttachmentItemDto? deletePod;
13891390
private string? currentUsername;
1391+
private int? appliedInitialDocNum;
1392+
private bool appliedInitialViewLatest;
13901393

13911394
[SupplyParameterFromQuery(Name = "docNum")]
13921395
public int? InitialDocNum { get; set; }
13931396

1397+
[SupplyParameterFromQuery(Name = "viewLatest")]
1398+
public bool InitialViewLatest { get; set; }
1399+
13941400
protected override async Task OnInitializedAsync()
13951401
{
13961402
var authState = await AuthStateProvider.GetAuthenticationStateAsync();
13971403
currentUsername = authState.User.Identity?.Name;
1404+
}
1405+
1406+
protected override async Task OnParametersSetAsync()
1407+
{
1408+
await ApplyInitialNavigationAsync();
1409+
}
1410+
1411+
private async Task ApplyInitialNavigationAsync()
1412+
{
1413+
if (!InitialDocNum.HasValue || InitialDocNum.Value <= 0)
1414+
return;
13981415

1399-
if (InitialDocNum.HasValue && InitialDocNum.Value > 0)
1416+
if (appliedInitialDocNum == InitialDocNum.Value && appliedInitialViewLatest == InitialViewLatest)
1417+
return;
1418+
1419+
appliedInitialDocNum = InitialDocNum.Value;
1420+
appliedInitialViewLatest = InitialViewLatest;
1421+
1422+
uploadDocNum = InitialDocNum.Value;
1423+
filterSearch = InitialDocNum.Value.ToString(CultureInfo.InvariantCulture);
1424+
activeFilterSearch = filterSearch;
1425+
1426+
await LookupInvoice();
1427+
await ReloadPodsTableAsync(resetToFirstPage: true);
1428+
1429+
if (InitialViewLatest)
14001430
{
1401-
uploadDocNum = InitialDocNum.Value;
1402-
await LookupInvoice();
1431+
await OpenLatestPodForLookupInvoiceAsync();
1432+
}
1433+
}
1434+
1435+
private async Task OpenLatestPodForLookupInvoiceAsync()
1436+
{
1437+
if (lookupInvoice == null)
1438+
return;
1439+
1440+
try
1441+
{
1442+
var response = await PodService.GetInvoicePodsAsync(lookupInvoice.DocEntry);
1443+
var latestAttachment = response?.Attachments?
1444+
.OrderByDescending(attachment => attachment.UploadedAt)
1445+
.FirstOrDefault();
1446+
1447+
if (latestAttachment == null)
1448+
{
1449+
uploadSuccess = false;
1450+
uploadMessage = $"No POD upload was found for invoice #{lookupInvoice.DocNum}.";
1451+
return;
1452+
}
1453+
1454+
await ViewPod(new PodAttachmentItemDto
1455+
{
1456+
Id = latestAttachment.Id,
1457+
FileName = latestAttachment.FileName,
1458+
MimeType = latestAttachment.MimeType,
1459+
FileSizeBytes = latestAttachment.FileSizeBytes,
1460+
FileSizeFormatted = latestAttachment.FileSizeFormatted,
1461+
Description = latestAttachment.Description,
1462+
UploadedAt = latestAttachment.UploadedAt,
1463+
UploadedByUserName = latestAttachment.UploadedByUserName,
1464+
DownloadUrl = latestAttachment.DownloadUrl,
1465+
InvoiceDocEntry = lookupInvoice.DocEntry,
1466+
InvoiceDocNum = lookupInvoice.DocNum,
1467+
CardCode = lookupInvoice.CardCode,
1468+
CardName = lookupInvoice.CardName
1469+
});
1470+
}
1471+
catch (Exception ex)
1472+
{
1473+
Logger.LogError(ex, "Error opening latest POD for invoice {DocNum}", lookupInvoice.DocNum);
1474+
uploadSuccess = false;
1475+
uploadMessage = "Failed to open the uploaded POD.";
14031476
}
14041477
}
14051478

0 commit comments

Comments
 (0)