Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group = 'com.flexcodelabs'
version = '0.0.63'
version = '0.0.64'
description = 'Flextuma App'

java {
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,16 @@ public class WhatsAppInboxMessage extends Owner {
@Column(columnDefinition = "TEXT")
private String caption;

/** Filename under the configured media directory once the bytes are downloaded from Meta. Null if never downloaded or the download failed. */
/** Tenant-scoped path ("tenantFolder/filename") under the configured media directory once
* the bytes are downloaded from Meta. Null if never downloaded or the download failed. */
@Column(name = "media_path")
private String mediaPath;

/** Size in bytes of the downloaded media file. Null if never downloaded. Used to compute
* per-tenant WhatsApp media storage usage. */
@Column(name = "media_size")
private Long mediaSize;

@Column(name = "received_at", nullable = false)
private LocalDateTime receivedAt;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
package com.flexcodelabs.flextuma.core.repositories;

import com.flexcodelabs.flextuma.core.entities.auth.Organisation;
import com.flexcodelabs.flextuma.core.entities.auth.User;
import com.flexcodelabs.flextuma.core.entities.whatsapp.WhatsAppInboxMessage;
import com.flexcodelabs.flextuma.modules.whatsapp.dtos.WhatsAppTenantStorageUsageDTO;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.UUID;

@Repository
public interface WhatsAppInboxMessageRepository extends BaseRepository<WhatsAppInboxMessage, UUID>,
JpaSpecificationExecutor<WhatsAppInboxMessage> {
boolean existsByProviderMessageId(String providerMessageId);

/** Bytes of WhatsApp media stored for one tenant: everyone in {@code organisation} when it
* is non-null, otherwise just {@code user} (the org-less-account fallback). */
@Query("SELECT COALESCE(SUM(m.mediaSize), 0) FROM WhatsAppInboxMessage m WHERE m.mediaSize IS NOT NULL AND "
+ "((:organisation IS NOT NULL AND m.createdBy.organisation = :organisation) "
+ "OR (:organisation IS NULL AND m.createdBy = :user))")
long sumMediaStorageBytes(@Param("organisation") Organisation organisation, @Param("user") User user);

/** Count of stored media files for the same tenant scope as {@link #sumMediaStorageBytes}. */
@Query("SELECT COUNT(m) FROM WhatsAppInboxMessage m WHERE m.mediaSize IS NOT NULL AND "
+ "((:organisation IS NOT NULL AND m.createdBy.organisation = :organisation) "
+ "OR (:organisation IS NULL AND m.createdBy = :user))")
long countMediaForTenant(@Param("organisation") Organisation organisation, @Param("user") User user);

/** Storage breakdown across every tenant (organisation, or org-less user), for admin views. */
@Query("SELECT new com.flexcodelabs.flextuma.modules.whatsapp.dtos.WhatsAppTenantStorageUsageDTO("
+ "COALESCE(o.id, u.id), COALESCE(o.name, u.username), SUM(m.mediaSize), COUNT(m)) "
+ "FROM WhatsAppInboxMessage m JOIN m.createdBy u LEFT JOIN u.organisation o "
+ "WHERE m.mediaSize IS NOT NULL "
+ "GROUP BY COALESCE(o.id, u.id), COALESCE(o.name, u.username) "
+ "ORDER BY SUM(m.mediaSize) DESC")
List<WhatsAppTenantStorageUsageDTO> findStorageUsageByTenant();
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import com.flexcodelabs.flextuma.core.dtos.Pagination;
import com.flexcodelabs.flextuma.core.entities.whatsapp.WhatsAppInboxMessage;
import com.flexcodelabs.flextuma.modules.whatsapp.dtos.WhatsAppConversationDTO;
import com.flexcodelabs.flextuma.modules.whatsapp.dtos.WhatsAppTenantStorageUsageDTO;
import com.flexcodelabs.flextuma.modules.whatsapp.services.WhatsAppInboxMessageService;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

Expand Down Expand Up @@ -41,6 +43,11 @@ public ResponseEntity<byte[]> media(@PathVariable UUID id) {
return ResponseEntity.ok().contentType(contentType).body(media.bytes());
}

@GetMapping("/storage-usage")
public List<WhatsAppTenantStorageUsageDTO> storageUsage() {
return service.storageUsage();
}

@GetMapping("/conversations")
public Map<String, Object> conversations(
@RequestParam(defaultValue = "0") int page,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,10 @@ private void attachMedia(WhatsAppInboxMessage message, WhatsAppWebhookConfig con
message.setMediaId(mediaId.toString());
message.setMimeType(mimeType != null ? mimeType.toString() : null);
message.setCaption(caption != null ? caption.toString() : null);
mediaService.download(config, mediaId.toString()).ifPresent(message::setMediaPath);
mediaService.download(config, mediaId.toString()).ifPresent(downloaded -> {
message.setMediaPath(downloaded.path());
message.setMediaSize(downloaded.size());
});
}

private String extractInboundContent(Map<String, Object> raw, String type) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.flexcodelabs.flextuma.modules.whatsapp.dtos;

import java.util.UUID;

import lombok.Builder;

/** Total WhatsApp media storage for one tenant: an organisation, or an individual user for
* org-less accounts. */
@Builder
public record WhatsAppTenantStorageUsageDTO(
UUID tenantId,
String tenantLabel,
long totalBytes,
long mediaCount) {
}
Loading