diff --git a/app/javascript/dashboard/components-next/whatsapp/WhatsAppTemplateParser.vue b/app/javascript/dashboard/components-next/whatsapp/WhatsAppTemplateParser.vue index cf62a6d5d..6df06642c 100644 --- a/app/javascript/dashboard/components-next/whatsapp/WhatsAppTemplateParser.vue +++ b/app/javascript/dashboard/components-next/whatsapp/WhatsAppTemplateParser.vue @@ -72,6 +72,10 @@ const formatType = computed(() => { return format ? format.charAt(0) + format.slice(1).toLowerCase() : ''; }); +const isDocumentTemplate = computed(() => { + return headerComponent.value?.format?.toLowerCase() === 'document'; +}); + const hasVariables = computed(() => { return bodyText.value?.match(/{{([^}]+)}}/g) !== null; }); @@ -126,6 +130,11 @@ const updateMediaUrl = value => { processedParams.value.header.media_url = value; }; +const updateMediaName = value => { + processedParams.value.header ??= {}; + processedParams.value.header.media_name = value; +}; + const sendMessage = () => { v$.value.$touch(); if (v$.value.$invalid) return; @@ -168,10 +177,12 @@ defineExpose({ processedParams, hasVariables, hasMediaHeader, + isDocumentTemplate, headerComponent, renderedTemplate, v$, updateMediaUrl, + updateMediaName, sendMessage, resetTemplate, goBack, @@ -225,6 +236,17 @@ defineExpose({ @update:model-value="updateMediaUrl" /> +
+ +
diff --git a/app/javascript/dashboard/helper/specs/templateHelper.spec.js b/app/javascript/dashboard/helper/specs/templateHelper.spec.js index 6e0661152..375e38a2d 100644 --- a/app/javascript/dashboard/helper/specs/templateHelper.spec.js +++ b/app/javascript/dashboard/helper/specs/templateHelper.spec.js @@ -218,6 +218,7 @@ describe('templateHelper', () => { expect(result.header).toEqual({ media_url: '', media_type: 'document', + media_name: '', }); expect(result.body).toEqual({ 1: '', diff --git a/app/javascript/dashboard/helper/templateHelper.js b/app/javascript/dashboard/helper/templateHelper.js index 5c9bbff05..1fb61d760 100644 --- a/app/javascript/dashboard/helper/templateHelper.js +++ b/app/javascript/dashboard/helper/templateHelper.js @@ -51,6 +51,11 @@ export const buildTemplateParameters = (template, hasMediaHeaderValue) => { if (!allVariables.header) allVariables.header = {}; allVariables.header.media_url = ''; allVariables.header.media_type = headerComponent.format.toLowerCase(); + + // For document templates, include media_name field for filename support + if (headerComponent.format.toLowerCase() === 'document') { + allVariables.header.media_name = ''; + } } // Process button variables diff --git a/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json index 5f53faaa8..cf28312dc 100644 --- a/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json +++ b/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json @@ -40,6 +40,7 @@ "BUTTON_LABEL": "Button {index}", "COUPON_CODE": "Enter coupon code (max 15 chars)", "MEDIA_URL_LABEL": "Enter {type} URL", + "DOCUMENT_NAME_PLACEHOLDER": "Enter document filename (e.g., Invoice_2025.pdf)", "BUTTON_PARAMETER": "Enter button parameter" } } diff --git a/app/services/whatsapp/populate_template_parameters_service.rb b/app/services/whatsapp/populate_template_parameters_service.rb index 278e52f64..3f9f64b91 100644 --- a/app/services/whatsapp/populate_template_parameters_service.rb +++ b/app/services/whatsapp/populate_template_parameters_service.rb @@ -30,12 +30,12 @@ class Whatsapp::PopulateTemplateParametersService end end - def build_media_parameter(url, media_type) + def build_media_parameter(url, media_type, media_name = nil) return nil if url.blank? sanitized_url = sanitize_parameter(url) validate_url(sanitized_url) - build_media_type_parameter(sanitized_url, media_type.downcase) + build_media_type_parameter(sanitized_url, media_type.downcase, media_name) end def build_named_parameter(parameter_name, value) @@ -89,14 +89,14 @@ class Whatsapp::PopulateTemplateParametersService } end - def build_media_type_parameter(sanitized_url, media_type) + def build_media_type_parameter(sanitized_url, media_type, media_name = nil) case media_type when 'image' build_image_parameter(sanitized_url) when 'video' build_video_parameter(sanitized_url) when 'document' - build_document_parameter(sanitized_url) + build_document_parameter(sanitized_url, media_name) else raise ArgumentError, "Unsupported media type: #{media_type}" end @@ -110,8 +110,11 @@ class Whatsapp::PopulateTemplateParametersService { type: 'video', video: { link: url } } end - def build_document_parameter(url) - { type: 'document', document: { link: url } } + def build_document_parameter(url, media_name = nil) + document_params = { link: url } + document_params[:filename] = media_name if media_name.present? + + { type: 'document', document: document_params } end def rich_formatting?(text) diff --git a/app/services/whatsapp/providers/whatsapp_cloud_service.rb b/app/services/whatsapp/providers/whatsapp_cloud_service.rb index 68e965595..124e1e5d3 100644 --- a/app/services/whatsapp/providers/whatsapp_cloud_service.rb +++ b/app/services/whatsapp/providers/whatsapp_cloud_service.rb @@ -141,7 +141,11 @@ class Whatsapp::Providers::WhatsappCloudService < Whatsapp::Providers::BaseServi # { # processed_params: { # body: { '1': 'John', '2': '123 Main St' }, - # header: { media_url: 'https://...', media_type: 'image' }, + # header: { + # media_url: 'https://...', + # media_type: 'image', + # media_name: 'filename.pdf' # Optional, for document templates only + # }, # buttons: [{ type: 'url', parameter: 'otp123456' }] # } # } diff --git a/app/services/whatsapp/template_processor_service.rb b/app/services/whatsapp/template_processor_service.rb index 3b12bf58b..4a89d684a 100644 --- a/app/services/whatsapp/template_processor_service.rb +++ b/app/services/whatsapp/template_processor_service.rb @@ -60,9 +60,10 @@ class Whatsapp::TemplateProcessorService next if value.blank? if media_url_with_type?(key, header_data) - media_param = parameter_builder.build_media_parameter(value, header_data['media_type']) + media_name = header_data['media_name'] + media_param = parameter_builder.build_media_parameter(value, header_data['media_type'], media_name) header_params << media_param if media_param - elsif key != 'media_type' + elsif key != 'media_type' && key != 'media_name' header_params << parameter_builder.build_parameter(value) end end