github.com/companieshouse/lfp-pay-api@v0.0.0-20230203133422-0ca455cd79f9/service/email_service.go (about)

     1  package service
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"strconv"
     8  	"time"
     9  
    10  	"github.com/companieshouse/chs.go/avro"
    11  	"github.com/companieshouse/chs.go/avro/schema"
    12  	"github.com/companieshouse/chs.go/kafka/producer"
    13  	"github.com/companieshouse/filing-notification-sender/util"
    14  	"github.com/companieshouse/lfp-pay-api-core/models"
    15  	"github.com/companieshouse/lfp-pay-api/config"
    16  )
    17  
    18  const lfpReceivedAppID = "lfp-pay-api.late_filing_penalty_received_email"
    19  const lfpFilingDescription = "Late Filing Penalty"
    20  const lfpMessageType = "late_filing_penalty_received_email"
    21  
    22  // ProducerTopic is the topic to which the email-send kafka message is sent
    23  const ProducerTopic = "email-send"
    24  
    25  // ProducerSchemaName is the schema which will be used to send the email-send kafka message with
    26  const ProducerSchemaName = "email-send"
    27  
    28  // SendEmailKafkaMessage sends a kafka message to the email-sender to send an email
    29  func SendEmailKafkaMessage(payableResource models.PayableResource, req *http.Request) error {
    30  	cfg, err := config.Get()
    31  	if err != nil {
    32  		err = fmt.Errorf("error getting config for kafka message production: [%v]", err)
    33  		return err
    34  	}
    35  
    36  	// Get a producer
    37  	kafkaProducer, err := producer.New(&producer.Config{Acks: &producer.WaitForAll, BrokerAddrs: cfg.BrokerAddr})
    38  	if err != nil {
    39  		err = fmt.Errorf("error creating kafka producer: [%v]", err)
    40  		return err
    41  	}
    42  	emailSendSchema, err := schema.Get(cfg.SchemaRegistryURL, ProducerSchemaName)
    43  	if err != nil {
    44  		err = fmt.Errorf("error getting schema from schema registry: [%v]", err)
    45  		return err
    46  	}
    47  	producerSchema := &avro.Schema{
    48  		Definition: emailSendSchema,
    49  	}
    50  
    51  	// Prepare a message with the avro schema
    52  	message, err := prepareKafkaMessage(*producerSchema, payableResource, req)
    53  	if err != nil {
    54  		err = fmt.Errorf("error preparing kafka message with schema: [%v]", err)
    55  		return err
    56  	}
    57  
    58  	// Send the message
    59  	partition, offset, err := kafkaProducer.Send(message)
    60  	if err != nil {
    61  		err = fmt.Errorf("failed to send message in partition: %d at offset %d", partition, offset)
    62  		return err
    63  	}
    64  	return nil
    65  }
    66  
    67  // prepareKafkaMessage generates the kafka message that is to be sent
    68  func prepareKafkaMessage(emailSendSchema avro.Schema, payableResource models.PayableResource, req *http.Request) (*producer.Message, error) {
    69  	cfg, err := config.Get()
    70  	if err != nil {
    71  		err = fmt.Errorf("error getting config: [%v]", err)
    72  		return nil, err
    73  	}
    74  
    75  	// Access Company Name to be included in the email
    76  	companyName, err := GetCompanyName(payableResource.CompanyNumber, req)
    77  	if err != nil {
    78  		err = fmt.Errorf("error getting company name: [%v]", err)
    79  		return nil, err
    80  	}
    81  
    82  	// Access specific transaction that was paid for
    83  	payedTransaction, err := GetTransactionForPenalty(payableResource.CompanyNumber, payableResource.Transactions[0].TransactionID)
    84  	if err != nil {
    85  		err = fmt.Errorf("error getting transaction for LFP: [%v]", err)
    86  		return nil, err
    87  	}
    88  
    89  	// Convert madeUpDate and transactionDate to readable format for email
    90  	madeUpDate, err := time.Parse("2006-01-02", payedTransaction.MadeUpDate)
    91  	if err != nil {
    92  		err = fmt.Errorf("error parsing made up date: [%v]", err)
    93  		return nil, err
    94  	}
    95  	transactionDate, err := time.Parse("2006-01-02", payedTransaction.TransactionDate)
    96  	if err != nil {
    97  		err = fmt.Errorf("error parsing penalty date: [%v]", err)
    98  		return nil, err
    99  	}
   100  
   101  	// Set dataField to be used in the avro schema.
   102  	dataFieldMessage := models.DataField{
   103  		PayableResource:   payableResource,
   104  		TransactionID:     payableResource.Transactions[0].TransactionID,
   105  		MadeUpDate:        madeUpDate.Format("2 January 2006"),
   106  		TransactionDate:   transactionDate.Format("2 January 2006"),
   107  		Amount:            fmt.Sprintf("%g", payedTransaction.OriginalAmount),
   108  		CompanyName:       companyName,
   109  		FilingDescription: lfpFilingDescription,
   110  		To:                payableResource.CreatedBy.Email,
   111  		Subject:           fmt.Sprintf("Confirmation of your Companies House penalty payment"),
   112  		CHSURL:            cfg.CHSURL,
   113  	}
   114  
   115  	dataBytes, err := json.Marshal(dataFieldMessage)
   116  	if err != nil {
   117  		err = fmt.Errorf("error marshalling dataFieldMessage: [%v]", err)
   118  		return nil, err
   119  	}
   120  
   121  	messageID := "<" + payableResource.Reference + "." + strconv.Itoa(util.Random(0, 100000)) + "@companieshouse.gov.uk>"
   122  
   123  	emailSendMessage := models.EmailSend{
   124  		AppID:        lfpReceivedAppID,
   125  		MessageID:    messageID,
   126  		MessageType:  lfpMessageType,
   127  		Data:         string(dataBytes),
   128  		EmailAddress: payableResource.CreatedBy.Email,
   129  		CreatedAt:    time.Now().String(),
   130  	}
   131  
   132  	messageBytes, err := emailSendSchema.Marshal(emailSendMessage)
   133  	if err != nil {
   134  		err = fmt.Errorf("error marshalling email send message: [%v]", err)
   135  		return nil, err
   136  	}
   137  
   138  	producerMessage := &producer.Message{
   139  		Value: messageBytes,
   140  		Topic: ProducerTopic,
   141  	}
   142  	return producerMessage, nil
   143  }