Java tutorial
/* This file is part of Cyclos. Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.aop; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import nl.strohalm.cyclos.dao.exceptions.EntityNotFoundException; import nl.strohalm.cyclos.entities.Entity; import nl.strohalm.cyclos.entities.access.Channel; import nl.strohalm.cyclos.entities.access.MemberUser; import nl.strohalm.cyclos.entities.access.User; import nl.strohalm.cyclos.entities.accounts.Account; import nl.strohalm.cyclos.entities.accounts.AccountOwner; import nl.strohalm.cyclos.entities.accounts.AccountStatus; import nl.strohalm.cyclos.entities.accounts.AccountType; import nl.strohalm.cyclos.entities.accounts.MemberAccount; import nl.strohalm.cyclos.entities.accounts.MemberGroupAccountSettings; import nl.strohalm.cyclos.entities.accounts.SystemAccountOwner; import nl.strohalm.cyclos.entities.accounts.guarantees.Certification; import nl.strohalm.cyclos.entities.accounts.guarantees.Guarantee; import nl.strohalm.cyclos.entities.accounts.guarantees.GuaranteeType; import nl.strohalm.cyclos.entities.accounts.guarantees.PaymentObligation; import nl.strohalm.cyclos.entities.accounts.loans.Loan; import nl.strohalm.cyclos.entities.accounts.loans.LoanPayment; import nl.strohalm.cyclos.entities.accounts.transactions.AuthorizationLevel; import nl.strohalm.cyclos.entities.accounts.transactions.Invoice; import nl.strohalm.cyclos.entities.accounts.transactions.Payment; import nl.strohalm.cyclos.entities.accounts.transactions.PaymentRequestTicket; import nl.strohalm.cyclos.entities.accounts.transactions.ScheduledPayment; import nl.strohalm.cyclos.entities.accounts.transactions.Transfer; import nl.strohalm.cyclos.entities.accounts.transactions.AuthorizationLevel.Authorizer; import nl.strohalm.cyclos.entities.ads.Ad; import nl.strohalm.cyclos.entities.groups.Group; import nl.strohalm.cyclos.entities.groups.MemberGroup; import nl.strohalm.cyclos.entities.members.Element; import nl.strohalm.cyclos.entities.members.Member; import nl.strohalm.cyclos.entities.members.Reference; import nl.strohalm.cyclos.entities.members.TransactionFeedback; import nl.strohalm.cyclos.entities.members.TransactionFeedbackRequest; import nl.strohalm.cyclos.entities.members.brokerings.BrokerCommissionContract; import nl.strohalm.cyclos.entities.members.brokerings.Brokering; import nl.strohalm.cyclos.entities.members.messages.Message; import nl.strohalm.cyclos.entities.services.ServiceClient; import nl.strohalm.cyclos.entities.settings.LocalSettings; import nl.strohalm.cyclos.entities.settings.MessageSettings; import nl.strohalm.cyclos.entities.tokens.Token; import nl.strohalm.cyclos.exceptions.UnexpectedEntityException; import nl.strohalm.cyclos.services.access.ChangeLoginPasswordDTO; import nl.strohalm.cyclos.services.access.ChannelService; import nl.strohalm.cyclos.services.access.exceptions.BlockedCredentialsException; import nl.strohalm.cyclos.services.accounts.AccountService; import nl.strohalm.cyclos.services.accounts.GetTransactionsDTO; import nl.strohalm.cyclos.services.accounts.guarantees.CertificationService; import nl.strohalm.cyclos.services.accounts.guarantees.PaymentObligationService; import nl.strohalm.cyclos.services.accounts.pos.exceptions.PosPinBlockedException; import nl.strohalm.cyclos.services.elements.*; import nl.strohalm.cyclos.services.fetch.FetchService; import nl.strohalm.cyclos.services.groups.GroupService; import nl.strohalm.cyclos.services.preferences.MessageChannel; import nl.strohalm.cyclos.services.preferences.PreferenceService; import nl.strohalm.cyclos.services.settings.SettingsService; import nl.strohalm.cyclos.services.tokens.GenerateTokenDTO; import nl.strohalm.cyclos.services.tokens.ResetPinTokenData; import nl.strohalm.cyclos.services.tokens.SenderRedeemTokenData; import nl.strohalm.cyclos.services.tokens.TokenService; import nl.strohalm.cyclos.services.transactions.DoExternalPaymentDTO; import nl.strohalm.cyclos.services.transactions.InvoiceService; import nl.strohalm.cyclos.services.transactions.TicketService; import nl.strohalm.cyclos.services.transactions.TransferDTO; import nl.strohalm.cyclos.utils.DateHelper; import nl.strohalm.cyclos.utils.MessageProcessingHelper; import nl.strohalm.cyclos.utils.MessageResolver; import nl.strohalm.cyclos.utils.RelationshipHelper; import nl.strohalm.cyclos.utils.access.LoggedUser; import nl.strohalm.cyclos.utils.conversion.UnitsConverter; import nl.strohalm.cyclos.utils.sms.SmsSender; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; /** * Aspect used to notify members about various events on the system * * @author jefferson */ @Aspect public class MessageAspect { private static final float PRECISION_DELTA = 0.0001F; private AccountService accountService; private BrokeringService brokeringService; private CertificationService certificationService; private ChannelService channelService; private ElementService elementService; private FetchService fetchService; private GroupService groupService; private InvoiceService invoiceService; private MessageService messageService; private PaymentObligationService paymentObligationService; private SettingsService settingsService; private TicketService ticketService; private TokenService tokenService; private TokenMessages tokenMessages; private MessageHelper messageHelper; /** * Store, for each member, the time in millis when the low units alert was sent. Used to not send the alert twice a day */ private final Set<Long> sentLowUnits = Collections.synchronizedSet(new HashSet<Long>()); private Calendar lastPaymentDate; private MessageResolver messageResolver; private PreferenceService preferenceService; private SmsSender smsSender; @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.InvoiceService.accept*(..))", returning = "invoice", argNames = "invoice") public void acceptedInvoiceNotification(final Invoice invoice) { // Get the destination final Member destinationMember = invoice.getFromMember(); if (destinationMember == null) { // The invoice was sent from system return; } // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getInvoiceAcceptedSubject(); final String body = messageSettings.getInvoiceAcceptedMessage(); final String sms = messageSettings.getInvoiceAcceptedSms(); // Process message body final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, invoice.getTo(), invoice); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, invoice.getTo(), invoice); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, invoice.getTo(), invoice); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.INVOICE); message.setEntity(invoice); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); notifyTransactionFeedbackRequest(invoice.getTransfer()); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.PaymentService.insertWithNotification(..)) && args(dto)", argNames = "transfer, dto", returning = "transfer") public void automaticPaymentReceivedNotification(Transfer transfer, final TransferDTO dto) { transfer = fetchService.fetch(transfer, RelationshipHelper.nested(Transfer.Relationships.TO, MemberAccount.Relationships.MEMBER), Transfer.Relationships.TYPE); if (transfer.isRoot() && !transfer.isToSystem()) { // Get the destination final Member destinationMember = (Member) transfer.getTo().getOwner(); final Set<MessageChannel> channels = preferenceService.receivedChannels(destinationMember, Message.Type.PAYMENT); if (!channels.isEmpty()) { AccountStatus status = null; final boolean sendSmsNotification = transfer.getType().isAllowSmsNotification() && channels.contains(MessageChannel.SMS); if (sendSmsNotification) { status = accountService.getStatus(new GetTransactionsDTO(transfer.getTo())); } // Get the message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); String subject = null; String body = null; String sms = null; if (transfer.getAccountFeeLog() != null) { subject = messageSettings.getAccountFeeReceivedSubject(); body = messageSettings.getAccountFeeReceivedMessage(); if (sendSmsNotification) { sms = messageSettings.getAccountFeeReceivedSms(); } // Process message content subject = MessageProcessingHelper.processVariables(subject, localSettings, destinationMember, transfer, transfer.getAccountFeeLog().getAccountFee()); body = MessageProcessingHelper.processVariables(body, localSettings, destinationMember, transfer, transfer.getAccountFeeLog().getAccountFee()); if (sendSmsNotification) { sms = MessageProcessingHelper.processVariables(sms, localSettings, destinationMember, transfer, transfer.getAccountFeeLog().getAccountFee(), status); } } else { // Check if the transfer has been processed or awaits authorization if (transfer.getProcessDate() == null) { subject = messageSettings.getPendingPaymentReceivedSubject(); body = messageSettings.getPendingPaymentReceivedMessage(); if (sendSmsNotification) { sms = messageSettings.getPendingPaymentReceivedSms(); } } else { subject = messageSettings.getPaymentReceivedSubject(); body = messageSettings.getPaymentReceivedMessage(); if (sendSmsNotification) { sms = messageSettings.getPaymentReceivedSms(); } } // Process message content subject = MessageProcessingHelper.processVariables(subject, localSettings, transfer.getFrom().getOwner(), transfer); body = MessageProcessingHelper.processVariables(body, localSettings, transfer.getFrom().getOwner(), transfer); if (sendSmsNotification) { sms = MessageProcessingHelper.processVariables(sms, localSettings, transfer.getFrom().getOwner(), transfer, status); } } // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.PAYMENT); message.setEntity(transfer); message.setToMember(destinationMember); message.setSubject(subject); message.setBody(body); message.setSms(sms); // Send the message messageService.sendFromSystem(message); } } } @AfterThrowing(value = "target(nl.strohalm.cyclos.services.access.AccessService)", throwing = "e", argNames = "e") public void blockedCredentialsNotification(final BlockedCredentialsException e) { final User user = e.getUser(); if (user instanceof MemberUser) { boolean skipSms = false; try { // Try to get the current channel from the web services context, which will only return something when running on web services final Channel currentChannel = (Channel) Class .forName("mp.platform.cyclone.webservices.WebServiceContext").getMethod("getChannel") .invoke(null); if (currentChannel != null) { // Ok, we are running on a web service. skip if this is the SMS channel, as it has it's own notification final Channel smsChannel = channelService.getSmsChannel(); if (currentChannel.equals(smsChannel)) { // Do not notify by SMS skipSms = true; } } } catch (final Exception ex) { // SMS won't be skipped } final Member member = (Member) user.getElement(); // Get message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); String subject; String body; String sms; switch (e.getCredentialsType()) { case LOGIN_PASSWORD: subject = messageSettings.getLoginBlockedSubject(); body = messageSettings.getLoginBlockedMessage(); sms = skipSms ? null : messageSettings.getLoginBlockedSms(); break; case TRANSACTION_PASSWORD: subject = messageSettings.getMaxTransactionPasswordTriesSubject(); body = messageSettings.getMaxTransactionPasswordTriesMessage(); sms = skipSms ? null : messageSettings.getMaxTransactionPasswordTriesSms(); break; case PIN: subject = messageSettings.getPinBlockedSubject(); body = messageSettings.getPinBlockedMessage(); sms = skipSms ? null : messageSettings.getPinBlockedSms(); break; case CARD_SECURITY_CODE: subject = messageSettings.getCardSecurityCodeBlockedSubject(); body = messageSettings.getCardSecurityCodeBlockedMessage(); sms = skipSms ? null : messageSettings.getCardSecurityCodeBlockedSms(); break; default: throw e; } // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, member, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, member, localSettings); final String processedSms = sms == null ? null : MessageProcessingHelper.processVariables(sms, member, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.ACCESS); message.setToMember(member); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.InvoiceService.cancel*(..))", returning = "invoice", argNames = "invoice") public void cancelledInvoiceNotification(final Invoice invoice) { if (!invoice.isToSystem()) { // Get the destination final Member destinationMember = invoice.getToMember(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getInvoiceCancelledSubject(); final String body = messageSettings.getInvoiceCancelledMessage(); final String sms = messageSettings.getInvoiceCancelledSms(); // Process message body final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, invoice.getFrom(), invoice); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, invoice.getFrom(), invoice); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, invoice.getFrom(), invoice); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.INVOICE); message.setEntity(invoice); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.CertificationService.cancelCertificationAsMember(..)) && args(certificationId)", argNames = "certificationId") public void certificationCanceledNotification(final Long certificationId) { // Load the certification final Certification certification = certificationService.load(certificationId, Certification.Relationships.BUYER, Certification.Relationships.ISSUER); certificationStatusChangedNotification(certification); } @Around(value = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.CertificationService.save(..)) && args(certification)", argNames = "certification") public Certification certificationIssuedNotification(final ProceedingJoinPoint pjp, Certification certification) throws Throwable { // Check if it's a new certification final boolean isInsert = certification.isTransient(); // Save the certification certification = (Certification) pjp.proceed(); // If the certification has been registered and is active, notify buyer if (isInsert && certification.getStatus() == Certification.Status.ACTIVE) { // Get local and message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); // Get the destination final Member buyer = certification.getBuyer(); // Get the message settings final String subjectBuyer = messageSettings.getCertificationIssuedSubject(); final String bodyBuyer = messageSettings.getCertificationIssuedMessage(); final String smsBuyer = messageSettings.getCertificationIssuedSms(); // Process message content final String processedSubjectBuyer = MessageProcessingHelper.processVariables(subjectBuyer, certification, localSettings); final String processedBodyBuyer = MessageProcessingHelper.processVariables(bodyBuyer, certification, localSettings); final String processedSmsBuyer = MessageProcessingHelper.processVariables(smsBuyer, certification, localSettings); // Create the DTO final SendMessageFromSystemDTO messageToBuyer = new SendMessageFromSystemDTO(); messageToBuyer.setEntity(certification); messageToBuyer.setType(Message.Type.CERTIFICATION); messageToBuyer.setToMember(buyer); messageToBuyer.setSubject(processedSubjectBuyer); messageToBuyer.setBody(processedBodyBuyer); messageToBuyer.setSms(processedSmsBuyer); // Send the message messageService.sendFromSystem(messageToBuyer); } return certification; } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.CertificationService.processCertifications(..))", argNames = "certifications", returning = "certifications") public void certificationListStatusChangedNotification(final List<Certification> certifications) { for (final Certification certification : certifications) { certificationStatusChangedNotification(certification); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.CertificationService.changeStatus(..)) && args(certificationId, newStatus)", argNames = "certificationId, newStatus") public void certificationStatusChangedNotification(final Long certificationId, final Certification.Status newStatus) { // Load the certification final Certification certification = certificationService.load(certificationId, Certification.Relationships.BUYER, Certification.Relationships.ISSUER); certificationStatusChangedNotification(certification); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.CommissionService.acceptBrokerCommissionContract*(..))", returning = "brokerCommissionContract", argNames = "brokerCommissionContract") public void commissionContractAcceptedNotification(final BrokerCommissionContract brokerCommissionContract) { // Get the destination final Member destinationMember = brokerCommissionContract.getBrokering().getBroker(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getCommissionContractAcceptedSubject(); final String body = messageSettings.getCommissionContractAcceptedMessage(); final String sms = messageSettings.getCommissionContractAcceptedSms(); // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, brokerCommissionContract, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, brokerCommissionContract, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, brokerCommissionContract, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(brokerCommissionContract); message.setType(Message.Type.BROKERING); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.CommissionService.cancelBrokerCommissionContract*(..))", returning = "brokerCommissionContract", argNames = "brokerCommissionContract") public void commissionContractCancelledNotification(final BrokerCommissionContract brokerCommissionContract) { // Get the destination final Member destinationMember = brokerCommissionContract.getBrokering().getBrokered(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getCommissionContractCancelledSubject(); final String body = messageSettings.getCommissionContractCancelledMessage(); final String sms = messageSettings.getCommissionContractCancelledSms(); // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, brokerCommissionContract, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, brokerCommissionContract, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, brokerCommissionContract, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(brokerCommissionContract); message.setType(Message.Type.BROKERING); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.CommissionService.denyBrokerCommissionContract*(..))", returning = "brokerCommissionContract", argNames = "brokerCommissionContract") public void commissionContractDeniedNotification(final BrokerCommissionContract brokerCommissionContract) { // Get the destination final Member destinationMember = brokerCommissionContract.getBrokering().getBroker(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getCommissionContractDeniedSubject(); final String body = messageSettings.getCommissionContractDeniedMessage(); final String sms = messageSettings.getCommissionContractDeniedSms(); // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, brokerCommissionContract, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, brokerCommissionContract, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, brokerCommissionContract, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(brokerCommissionContract); message.setType(Message.Type.BROKERING); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.InvoiceService.deny*(..))", returning = "invoice", argNames = "invoice") public void deniedInvoiceNotification(final Invoice invoice) { if (!invoice.isFromSystem()) { // Get the destination final Member destinationMember = invoice.getFromMember(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getInvoiceDeniedSubject(); final String body = messageSettings.getInvoiceDeniedMessage(); final String sms = messageSettings.getInvoiceDeniedSms(); // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, invoice.getTo(), invoice); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, invoice.getTo(), invoice); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, invoice.getTo(), invoice); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.INVOICE); message.setEntity(invoice); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.ads.AdService.notifyExpiredAds(..))", returning = "ads", argNames = "ads") public void expiredAdsNotification(final List<Ad> ads) throws Throwable { final LocalSettings localSettings = settingsService.getLocalSettings(); // Get message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getAdExpirationSubject(); final String body = messageSettings.getAdExpirationMessage(); final String sms = messageSettings.getAdExpirationSms(); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.AD_EXPIRATION); for (final Ad ad : ads) { // Get the destination final Member owner = ad.getOwner(); message.setToMember(owner); // Process message content final String processedSubject = MessageProcessingHelper.processVariables(subject, ad, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, ad, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, ad, localSettings); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Process link and send message message.setEntity(ad); messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.BrokeringService.removeExpiredBrokerings(..))", returning = "brokerings", argNames = "brokerings") public void expiredBrokeringsNotification(final List<Brokering> brokerings) { final LocalSettings localSettings = settingsService.getLocalSettings(); // Get message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getBrokeringExpirationSubject(); final String body = messageSettings.getBrokeringExpirationMessage(); final String sms = messageSettings.getBrokeringExpirationSms(); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.BROKERING); for (final Brokering brokering : brokerings) { // Get the destination final Member member = brokering.getBroker(); message.setToMember(member); // Process message content final String processedSubject = MessageProcessingHelper.processVariables(subject, member, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, member, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, member, localSettings); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send message messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.InvoiceService.expireInvoice(..))", returning = "invoice", argNames = "invoice") public void expiredInvoiceNotification(final Invoice invoice) { // Get the settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final LocalSettings localSettings = settingsService.getLocalSettings(); // Send message to the sender of the invoice if (!invoice.isFromSystem()) { final String subjectSender = messageSettings.getSentInvoiceExpiredSubject(); final String bodySender = messageSettings.getSentInvoiceExpiredMessage(); final String smsSender = messageSettings.getSentInvoiceExpiredSms(); final String processedSubjectSender = MessageProcessingHelper.processVariables(subjectSender, localSettings, invoice.getTo(), invoice); final String processedBodySender = MessageProcessingHelper.processVariables(bodySender, localSettings, invoice.getTo(), invoice); final String processedSmsSender = MessageProcessingHelper.processVariables(smsSender, localSettings, invoice.getTo(), invoice); final SendMessageFromSystemDTO messageSender = new SendMessageFromSystemDTO(); messageSender.setType(Message.Type.INVOICE); messageSender.setEntity(invoice); messageSender.setToMember(invoice.getFromMember()); messageSender.setSubject(processedSubjectSender); messageSender.setBody(processedBodySender); messageSender.setSms(processedSmsSender); messageService.sendFromSystem(messageSender); } // Send message to the receiver of the invoice if (!invoice.isToSystem()) { final String subjectReceiver = messageSettings.getReceivedInvoiceExpiredSubject(); final String bodyReceiver = messageSettings.getReceivedInvoiceExpiredMessage(); final String smsReceiver = messageSettings.getReceivedInvoiceExpiredSms(); final String processedSubjectReceiver = MessageProcessingHelper.processVariables(subjectReceiver, localSettings, invoice.getFrom(), invoice); final String processedBodyReceiver = MessageProcessingHelper.processVariables(bodyReceiver, localSettings, invoice.getFrom(), invoice); final String processedSmsReceiver = MessageProcessingHelper.processVariables(smsReceiver, localSettings, invoice.getFrom(), invoice); final SendMessageFromSystemDTO messageReceiver = new SendMessageFromSystemDTO(); messageReceiver.setType(Message.Type.INVOICE); messageReceiver.setEntity(invoice); messageReceiver.setToMember(invoice.getToMember()); messageReceiver.setSubject(processedSubjectReceiver); messageReceiver.setBody(processedBodyReceiver); messageReceiver.setSms(processedSmsReceiver); messageService.sendFromSystem(messageReceiver); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.LoanService.alertExpiredLoans(..))", argNames = "payments", returning = "payments") public void expiredLoansNotification(final List<LoanPayment> payments) { final LocalSettings localSettings = settingsService.getLocalSettings(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getLoanExpirationSubject(); final String body = messageSettings.getLoanExpirationMessage(); final String sms = messageSettings.getLoanExpirationSms(); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.LOAN); for (final LoanPayment payment : payments) { // Set entity for link processing final Loan loan = payment.getLoan(); message.setEntity(loan); // Get the destination final Member member = (Member) loan.getTransfer().getTo().getOwner(); message.setToMember(member); // Process message content final String processedSubject = MessageProcessingHelper.processVariables(subject, loan, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, loan, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, loan, localSettings); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.PaymentService.confirmPayment(..)) && args(ticketString)", returning = "payment", argNames = "ticketString, payment") public void externalChannelPaymentConfirmed(final String ticketString, final Payment payment) { final PaymentRequestTicket prTicket = (PaymentRequestTicket) ticketService.load(ticketString, PaymentRequestTicket.Relationships.TO_CHANNEL); externalChannelPaymentNotification(payment, prTicket.getFromChannel(), prTicket.getToChannel()); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.PaymentService.insertExternalPayment(..)) && args(dto)", returning = "payment", argNames = "dto, payment") public void externalChannelPaymentPerformed(final DoExternalPaymentDTO dto, final Payment payment) { final String channelInternalName = dto.getChannel(); final Channel channel = channelService.loadByInternalName(channelInternalName); externalChannelPaymentNotification(payment, channel, null); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.TicketService.expirePaymentRequestTicket(..)) && args(ticket)", returning = "returningTicket", argNames = "ticket, returningTicket") public void externalChannelPaymentRequestExpired(final PaymentRequestTicket ticket, final PaymentRequestTicket returningTicket) { // Get local and message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); final Channel smsChannel = channelService.getSmsChannel(); // Only notify the payer if not on SMS channel final Channel toChannel = ticket.getToChannel(); final boolean skipToSms = toChannel.equals(smsChannel); final Map<String, Object> toVariables = ticket.getVariableValues(localSettings); toVariables.put("channel", toChannel.getDisplayName()); // Get payer message final Member payer = ticket.getFrom(); final String subjectPayer = messageSettings.getExternalChannelPaymentRequestExpiredPayerSubject(); final String bodyPayer = messageSettings.getExternalChannelPaymentRequestExpiredPayerMessage(); final String smsPayer = skipToSms ? null : messageSettings.getExternalChannelPaymentRequestExpiredPayerSms(); // Process payer message content final String processedSubjectPayer = MessageProcessingHelper.processVariables(subjectPayer, toVariables); final String processedBodyPayer = MessageProcessingHelper.processVariables(bodyPayer, toVariables); final String processedSmsPayer = smsPayer == null ? null : MessageProcessingHelper.processVariables(smsPayer, toVariables); // Create the payer DTO final SendMessageFromSystemDTO messageToPayer = new SendMessageFromSystemDTO(); messageToPayer.setToMember(payer); messageToPayer.setType(Message.Type.EXTERNAL_PAYMENT); messageToPayer.setSubject(processedSubjectPayer); messageToPayer.setBody(processedBodyPayer); messageToPayer.setSms(processedSmsPayer); // Send message to payer messageService.sendFromSystem(messageToPayer); // Only notify the payee if not on SMS channel final Channel fromChannel = ticket.getFromChannel(); final boolean skipFromSms = fromChannel.equals(smsChannel); final Map<String, Object> variableValues = ticket.getVariableValues(localSettings); variableValues.put("channel", fromChannel.getDisplayName()); // Get receiver message final Member receiver = ticket.getTo(); final String subjectReceiver = messageSettings.getExternalChannelPaymentRequestExpiredReceiverSubject(); final String bodyReceiver = messageSettings.getExternalChannelPaymentRequestExpiredReceiverMessage(); final String smsReceiver = skipFromSms ? null : messageSettings.getExternalChannelPaymentRequestExpiredReceiverSms(); // Process receiver message content final String processedSubjectReceiver = MessageProcessingHelper.processVariables(subjectReceiver, variableValues); final String processedBodyReceiver = MessageProcessingHelper.processVariables(bodyReceiver, variableValues); final String processedSmsReceiver = smsReceiver == null ? null : MessageProcessingHelper.processVariables(smsReceiver, variableValues); // Create the receiver DTO final SendMessageFromSystemDTO messageToReceiver = new SendMessageFromSystemDTO(); messageToReceiver.setToMember(receiver); messageToReceiver.setType(Message.Type.PAYMENT); messageToReceiver.setSubject(processedSubjectReceiver); messageToReceiver.setBody(processedBodyReceiver); messageToReceiver.setSms(processedSmsReceiver); // Send message to receiver messageService.sendFromSystem(messageToReceiver); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.LoanService.grant*(..))", argNames = "loan", returning = "loan") public void grantedLoanNotification(final Loan loan) { // Return when the loan is pending if (loan.getTransfer().getProcessDate() == null) { return; } // Get the destination final Member destinationMember = loan.getMember(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getLoanGrantedSubject(); final String body = messageSettings.getLoanGrantedMessage(); final String sms = messageSettings.getLoanGrantedSms(); // Process message contents final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, destinationMember, loan); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, destinationMember, loan); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, destinationMember, loan); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.LOAN); message.setEntity(loan); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.GuaranteeService.acceptGuaranteeAsMember(..))", argNames = "guarantee", returning = "guarantee") public void guaranteeAcceptedNotification(final Guarantee guarantee) { doGuaranteeStatusChangedNotification(guarantee, null); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.GuaranteeService.cancelGuaranteeAsMember(..))", argNames = "guarantee", returning = "guarantee") public void guaranteeCancelledNotification(final Guarantee guarantee) { doGuaranteeStatusChangedNotification(guarantee, null); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.GuaranteeService.denyGuaranteeAsMember(..))", argNames = "guarantee", returning = "guarantee") public void guaranteeDeniedNotification(final Guarantee guarantee) { doGuaranteeStatusChangedNotification(guarantee, null); } @AfterReturning(pointcut = "(execution(* nl.strohalm.cyclos.services.accounts.guarantees.GuaranteeService.requestGuarantee(..)) " + "|| execution(* nl.strohalm.cyclos.services.accounts.guarantees.GuaranteeService.registerGuarantee(..)))", returning = "guarantee") public void guaranteePendingIssuerNotification(final Guarantee guarantee) throws Throwable { if (guarantee.getStatus() == Guarantee.Status.PENDING_ISSUER) { // only send notification if the status is PENDING_ISSUER // Get local and message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); // Get the destination final Member toMember = guarantee.getIssuer(); // Get the message settings String subject = null; String body = null; String sms = null; if (guarantee.getGuaranteeType().getModel() == GuaranteeType.Model.WITH_BUYER_ONLY) { subject = messageSettings.getPendingBuyerOnlyGuaranteeIssuerSubject(); body = messageSettings.getPendingBuyerOnlyGuaranteeIssuerMessage(); sms = messageSettings.getPendingBuyerOnlyGuaranteeIssuerSms(); } else { subject = messageSettings.getPendingGuaranteeIssuerSubject(); body = messageSettings.getPendingGuaranteeIssuerMessage(); sms = messageSettings.getPendingGuaranteeIssuerSms(); } // Process message content final String processedSubject = MessageProcessingHelper.processVariables(subject, guarantee, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, guarantee, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, guarantee, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(guarantee); message.setType(Message.Type.GUARANTEE); message.setToMember(toMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.GuaranteeService.changeStatus(..))", argNames = "guarantee", returning = "guarantee") public void guaranteeStatusChangedNotification(final Guarantee guarantee) { // we don't use the previous status in the case doGuaranteeStatusChangedNotification(guarantee, null); } @Around(value = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.GuaranteeService.processGuarantee(..)) && args(guarantee,..)", argNames = "guarantee") public Guarantee guaranteeStatusChangedNotification(final ProceedingJoinPoint pjp, Guarantee guarantee) throws Throwable { final Guarantee.Status prevStatus = guarantee.getStatus(); guarantee = (Guarantee) pjp.proceed(); doGuaranteeStatusChangedNotification(guarantee, prevStatus); return guarantee; } @Around(value = "execution(* nl.strohalm.cyclos.services.elements.CommissionService.saveBrokerCommissionContract*(..)) && args(brokerCommissionContract)", argNames = "brokerCommissionContract") public BrokerCommissionContract newCommissionContractNotification(final ProceedingJoinPoint pjp, BrokerCommissionContract brokerCommissionContract) throws Throwable { final boolean isInsert = brokerCommissionContract.isTransient(); brokerCommissionContract = (BrokerCommissionContract) pjp.proceed(); // Send message if the contract is been inserted if (isInsert) { // Get message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getNewCommissionContractSubject(); final String body = messageSettings.getNewCommissionContractMessage(); final String sms = messageSettings.getNewCommissionContractSms(); // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, brokerCommissionContract, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, brokerCommissionContract, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, brokerCommissionContract, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(brokerCommissionContract); message.setType(Message.Type.BROKERING); message.setToMember(brokerCommissionContract.getBrokering().getBrokered()); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } return brokerCommissionContract; } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.TransferAuthorizationService.authorize*(..)) " + "|| execution(* nl.strohalm.cyclos.services.transactions.TransferAuthorizationService.deny*(..))", argNames = "transfer", returning = "transfer") public void paymentAuthorizedNotification(Transfer transfer) { transfer = fetchService.reload(transfer, Transfer.Relationships.AUTHORIZATIONS); if (CollectionUtils.isEmpty(transfer.getAuthorizations())) { return; } final AccountOwner fromOwner = transfer.getFromOwner(); final AccountOwner toOwner = transfer.getToOwner(); final List<Member> sendMessageTo = new ArrayList<Member>(); final boolean loggedAsPayer = LoggedUser.isValid() && LoggedUser.isMember() && LoggedUser.accountOwner().equals(fromOwner); if (!loggedAsPayer && (fromOwner instanceof Member)) { sendMessageTo.add((Member) fromOwner); } final boolean loggedAsReceiver = LoggedUser.isValid() && LoggedUser.isMember() && LoggedUser.accountOwner().equals(toOwner); if (!loggedAsReceiver && (toOwner instanceof Member)) { sendMessageTo.add((Member) toOwner); } if (!sendMessageTo.isEmpty()) { // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); String subject; String body; String sms; switch (transfer.getStatus()) { case PROCESSED: // Was authorized and processed subject = messageSettings.getPendingPaymentAuthorizedSubject(); body = messageSettings.getPendingPaymentAuthorizedMessage(); sms = messageSettings.getPendingPaymentAuthorizedSms(); break; case PENDING: // Was authorized but needs higher level if (fromOwner instanceof Member) { final Authorizer authorizer = transfer.getNextAuthorizationLevel().getAuthorizer(); final LocalSettings localSettings = settingsService.getLocalSettings(); final Member fromMember; switch (authorizer) { case BROKER: // Notify the broker if he currently has to authorize fromMember = fetchService.fetch((Member) fromOwner, Member.Relationships.BROKER); final Member broker = fromMember.getBroker(); if (broker != null) { subject = messageSettings.getNewPendingPaymentByBrokerSubject(); body = messageSettings.getNewPendingPaymentByBrokerMessage(); sms = messageSettings.getNewPendingPaymentByBrokerSms(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, fromMember, transfer); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, fromMember, transfer); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, fromMember, transfer); // Send the message final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.BROKERING); message.setEntity(transfer); message.setToMember(broker); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); messageService.sendFromSystem(message); } break; case PAYER: // Notify the payer if he currently has to authorize fromMember = (Member) fromOwner; final Member toMember = (Member) toOwner; subject = messageSettings.getNewPendingPaymentByPayerSubject(); body = messageSettings.getNewPendingPaymentByPayerMessage(); sms = messageSettings.getNewPendingPaymentByPayerSms(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, toMember, transfer); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, toMember, transfer); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, toMember, transfer); // Send the message final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.PAYMENT); message.setEntity(transfer); message.setToMember(fromMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); messageService.sendFromSystem(message); break; } } // If necessary, the message was already sent or the payment needs another authorization level return; case DENIED: // Was denied subject = messageSettings.getPendingPaymentDeniedSubject(); body = messageSettings.getPendingPaymentDeniedMessage(); sms = messageSettings.getPendingPaymentDeniedSms(); break; default: // Unknown status. return; } // Send the messages sendPaymentMessages(transfer, sendMessageTo, subject, body, sms); } // Send the transaction feedback request message notifyTransactionFeedbackRequest(transfer); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.TransferAuthorizationService.cancel*(..))", argNames = "transfer", returning = "transfer") public void paymentCancelledNotification(final Transfer transfer) { final AccountOwner fromOwner = transfer.getFromOwner(); final AccountOwner toOwner = transfer.getToOwner(); final boolean loggedAsSender = LoggedUser.isValid() && LoggedUser.isMember() && LoggedUser.accountOwner().equals(fromOwner); final List<Member> sendMessageTo = new ArrayList<Member>(); if (!loggedAsSender && (fromOwner instanceof Member)) { sendMessageTo.add((Member) fromOwner); } if (toOwner instanceof Member) { sendMessageTo.add((Member) toOwner); } // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getPendingPaymentCanceledSubject(); final String body = messageSettings.getPendingPaymentCanceledMessage(); final String sms = messageSettings.getPendingPaymentCanceledSms(); // Send the messages sendPaymentMessages(transfer, sendMessageTo, subject, body, sms); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.PaymentObligationService.changeStatus(..)) && args(paymentObligationId, newStatus)", argNames = "paymentObligationId, newStatus") public void paymentObligationPublishedNotification(final Long paymentObligationId, final PaymentObligation.Status newStatus) { // Load payment obligation final PaymentObligation paymentObligation = paymentObligationService.load(paymentObligationId, PaymentObligation.Relationships.SELLER); if (newStatus == PaymentObligation.Status.PUBLISHED) { // Get local and message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); // Notify the seller final Member toMember = paymentObligation.getSeller(); final String subject = messageSettings.getPaymentObligationRegisteredSubject(); final String body = messageSettings.getPaymentObligationRegisteredMessage(); final String sms = messageSettings.getPaymentObligationRegisteredSms(); // Process message content final String processedSubject = MessageProcessingHelper.processVariables(subject, paymentObligation, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, paymentObligation, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, paymentObligation, localSettings); // Create the message DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(paymentObligation); message.setType(Message.Type.PAYMENT_OBLIGATION); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); message.setToMember(toMember); messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.guarantees.PaymentObligationService.reject(..)) && args(paymentObligationId)", argNames = "paymentObligationId") public void paymentObligationRejectedNotification(final Long paymentObligationId) { // Load payment obligation final PaymentObligation paymentObligation = paymentObligationService.load(paymentObligationId, PaymentObligation.Relationships.BUYER); // Get local and message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); // Notify the buyer final Member toMember = paymentObligation.getBuyer(); final String subject = messageSettings.getPaymentObligationRejectedSubject(); final String body = messageSettings.getPaymentObligationRejectedMessage(); final String sms = messageSettings.getPaymentObligationRejectedSms(); // Process message content final String processedSubject = MessageProcessingHelper.processVariables(subject, paymentObligation, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, paymentObligation, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, paymentObligation, localSettings); // Create the message DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(paymentObligation); message.setType(Message.Type.PAYMENT_OBLIGATION); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); message.setToMember(toMember); messageService.sendFromSystem(message); } @AfterReturning(pointcut = "(execution(* nl.strohalm.cyclos.services.transactions.PaymentService.doPayment*(..)))", argNames = "payment", returning = "payment") public void paymentReceivedNotification(final Payment payment) { // A message is sent only when the payment is a transfer and the destination is a member (not system) MessageSettings messageSettings = settingsService.getMessageSettings(); if (payment instanceof Transfer && payment.getToOwner() instanceof Member) { final Transfer transfer = (Transfer) payment; // Get the message settings String subject; String body; String sms; // Check if the transfer has been processed or awaits authorization if (transfer.getProcessDate() == null) { if (getAuthorizer(transfer) == Authorizer.RECEIVER) { subject = messageSettings.getNewPendingPaymentByReceiverSubject(); body = messageSettings.getNewPendingPaymentByReceiverMessage(); sms = messageSettings.getNewPendingPaymentByReceiverSms(); } else { subject = messageSettings.getPendingPaymentReceivedSubject(); body = messageSettings.getPendingPaymentReceivedMessage(); sms = messageSettings.getPendingPaymentReceivedSms(); } } else { subject = messageSettings.getPaymentReceivedSubject(); body = messageSettings.getPaymentReceivedMessage(); sms = messageSettings.getPaymentReceivedSms(); } sendPaymentMessage(transfer, transfer.getTo(), transfer.getFrom(), subject, body, sms, Message.Type.PAYMENT); notifyBroker(transfer); } if (payment instanceof Transfer && payment.getFromOwner() instanceof Member) { final Transfer transfer = (Transfer) payment; sendPaymentMessage(transfer, transfer.getFrom(), transfer.getTo(), messageSettings.getPaymentSentSubject(), messageSettings.getPaymentSentMessage(), messageSettings.getPaymentSentSms(), Message.Type.PAYMENT_SENT); } // Request a transaction feedback for the payment source notifyTransactionFeedbackRequest(payment); // Perform the low units notification, if needed notifyLowUnits(payment); } private Authorizer getAuthorizer(Transfer transfer) { final AuthorizationLevel nextAuthorizationLevel = transfer.getNextAuthorizationLevel(); return nextAuthorizationLevel == null ? null : nextAuthorizationLevel.getAuthorizer(); } private void notifyBroker(Transfer payment) { MessageSettings messageSettings = settingsService.getMessageSettings(); LocalSettings localSettings = settingsService.getLocalSettings(); Authorizer authorizer = getAuthorizer(payment); // Notify the broker final Member fromMember = fetchService.fetch( payment.isFromSystem() ? null : (Member) payment.getFromOwner(), Member.Relationships.BROKER); final Member broker = fromMember == null ? null : fromMember.getBroker(); if (authorizer == Authorizer.BROKER && broker != null) { final String subject = messageSettings.getNewPendingPaymentByBrokerSubject(); final String body = messageSettings.getNewPendingPaymentByBrokerMessage(); final String sms = messageSettings.getNewPendingPaymentByBrokerSms(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, fromMember, payment); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, fromMember, payment); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, fromMember, payment); final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.BROKERING); message.setEntity(payment); message.setToMember(broker); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } private void sendPaymentMessage(Transfer payment, Account receiver, Account otherSide, String subject, String body, String sms, Message.Type type) { if (!payment.isRoot()) { return; } final LocalSettings localSettings = settingsService.getLocalSettings(); // Get the transfer authorizer, if any final Authorizer authorizer = getAuthorizer(payment); // Get the destination final Member destinationMember = (Member) receiver.getOwner(); final Set<MessageChannel> channels = preferenceService.receivedChannels(destinationMember, type); if (!channels.isEmpty()) { // The account status is only used in messages via SMS final boolean sendSmsNotification = payment.getType().isAllowSmsNotification() && channels.contains(MessageChannel.SMS); AccountStatus status = null; if (sendSmsNotification) { status = accountService.getStatus(new GetTransactionsDTO(receiver)); } // Process message contents final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, otherSide.getOwner(), payment); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, otherSide.getOwner(), payment); final String processedSms = sendSmsNotification ? MessageProcessingHelper.processVariables(sms, localSettings, otherSide.getOwner(), payment, status) : null; // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(type); message.setEntity(payment); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } @AfterThrowing(pointcut = "execution(* nl.strohalm.cyclos.services.accounts.pos.MemberPosService.checkPin(..)) && args(member, pin, posId)", throwing = "ppbe", argNames = "ppbe, member, pin, posId") public void posPinBlockedNotification(final PosPinBlockedException ppbe, final Member member, final String pin, final Long posId) { // Get message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getPosPinBlockedSubject(); final String body = messageSettings.getPosPinBlockedMessage(); final String sms = messageSettings.getPosPinBlockedSms(); final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, member, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, member, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, member, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.ACCESS); message.setToMember(member); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.ElementService.registerMember*(..)) && args(member, forceChange)", argNames = "member, forceChange") public void memberRegistered(final Member member, boolean forceChange) { sendRegistrationMessage(member); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.ElementService.publicRegisterMember*(..)) && args(member, remoteAddress)", argNames = "member, remoteAddress") public void memberRegisteredMember(Member member, String remoteAddress) { sendRegistrationMessage(member); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.ElementService.registerMemberByWebService*(..)) && args(*, member, *)", argNames = "member") public void memberRegisteredWS(Member member) { sendRegistrationMessage(member); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.tokens.TokenService.generateToken(..))", returning = "transactionId", argNames = "transactionId") public void tokenGenerated(String transactionId) { Token token = tokenService.loadTokenByTransactionId(transactionId); tokenMessages().sendGenerateTokenMessages(token); //agent performs payment, so need to inform him separately //we do nolt send payment SMS if (token.isIfSendNotification()) { paymentReceivedNotification(token.getTransferFrom()); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.tokens.TokenService.redeemToken(..)) && args(broker, tokenId, *, *)", argNames = "broker, tokenId") public void tokenRedeemed(Member broker, String tokenId) { tokenMessages().sendRedeemTokenMessages(broker, tokenService.loadTokenById(tokenId)); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.tokens.TokenService.senderRedeemToken(..)) && args(member, senderRedeemTokenData)", argNames = "member, senderRedeemTokenData") public void tokeRedeemedBySender(Member member, SenderRedeemTokenData senderRedeemTokenData) { sendRefundTokenMessage(senderRedeemTokenData); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.tokens.TokenService.resetPinToken(..)) && args(resetPinTokenData)", argNames = "resetPinTokenData") public void tokenPinResetByAdmin(ResetPinTokenData resetPinTokenData) { Token token = tokenService.loadTokenByTransactionId(resetPinTokenData.getTransactionId()); tokenMessages().sendResetPinTokenMessages(token); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.tokens.TokenService.refundToken(..)) && args(member, senderRedeemTokenData)", argNames = "member, senderRedeemTokenData") public void tokenRefunded(Member member, SenderRedeemTokenData senderRedeemTokenData) { sendRefundTokenMessage(senderRedeemTokenData); } private void sendRefundTokenMessage(SenderRedeemTokenData senderRedeemTokenData) { Token token = tokenService.loadTokenByTransactionId(senderRedeemTokenData.getTransactionId()); paymentReceivedNotification(token.getTransferTo()); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.access.AccessService.resetMemberTransactionPassword(..)) && args(dto)", argNames = "dto") public void memberTransactionPasswordResetByAdmin(ResetTransactionPasswordDTO dto) { transactionPasswordResetByAdmin(dto); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.access.AccessService.resetAdminTransactionPassword(..)) && args(dto)", argNames = "dto") public void adminTransactionPasswordResetByAdmin(ResetTransactionPasswordDTO dto) { transactionPasswordResetByAdmin(dto); } public void transactionPasswordResetByAdmin(ResetTransactionPasswordDTO dto) { //send message when reset but not blocked if (dto.isAllowGeneration()) { User user = dto.getUser(); MessageSettings messageSettings = settingsService.getMessageSettings(); final MemberUser memberUser = (MemberUser) fetchService.fetch(user, RelationshipHelper.nested(User.Relationships.ELEMENT, Element.Relationships.GROUP)); Member member = memberUser.getMember(); messageHelper().sendMemberMessage(messageSettings.getResetTransactionPasswordByAdminSubject(), messageSettings.getResetTransactionPasswordByAdminMessage(), messageSettings.getResetTransactionPasswordByAdminSms(), member, Message.Type.RESET_TRANSACTION_PASSWORD_BY_ADMIN); } } @AfterReturning(pointcut = "(execution(* nl.strohalm.cyclos.services.transactions.InvoiceService.send*(..)) && args(invoice))", argNames = "invoice") public void receivedInvoiceNotification(final Invoice invoice) { // Get the destination final Member destinationMember = invoice.getToMember(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getInvoiceReceivedSubject(); final String body = messageSettings.getInvoiceReceivedMessage(); final String sms = messageSettings.getInvoiceReceivedSms(); // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, invoice.getFrom(), invoice); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, invoice.getFrom(), invoice); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, invoice.getFrom(), invoice); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.INVOICE); message.setEntity(invoice); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.ReferenceService.saveMemberReference(..)) ||" + "execution(* nl.strohalm.cyclos.services.elements.ReferenceService.saveMyReference(..))", argNames = "reference", returning = "reference") public void receivedReferenceNotification(final Reference reference) { // Get the destination final Member destinationMember = reference.getTo(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getReferenceReceivedSubject(); final String body = messageSettings.getReferenceReceivedMessage(); final String sms = messageSettings.getReferenceReceivedSms(); // Process message contents final LocalSettings localSettings = settingsService.getLocalSettings(); final Member fromMember = reference.getFrom(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, fromMember, reference); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, fromMember, reference); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, fromMember, reference); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.REFERENCE); message.setEntity(reference); message.setToMember(destinationMember); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } @Before(value = "execution(* nl.strohalm.cyclos.services.elements.BrokeringService.changeBroker(..)) && args(dto)", argNames = "dto") public void removedBrokeringNotification(final ChangeBrokerDTO dto) { final Member member = dto.getMember(); final Brokering oldBrokering = brokeringService.getActiveBrokering(member); final Member oldBroker = (oldBrokering == null) ? null : oldBrokering.getBroker(); final Member newBroker = dto.getNewBroker(); final boolean justSuspendCommission = (oldBroker != null && oldBroker.equals(newBroker) && dto.isSuspendCommission()); if (!justSuspendCommission && oldBroker != null) { // Get message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getBrokeringRemovedSubject(); final String body = messageSettings.getBrokeringRemovedMessage(); final String sms = messageSettings.getBrokeringRemovedSms(); // Process message body final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, member, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, member, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, member, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.BROKERING); message.setToMember(oldBroker); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } @Around(value = "execution(* nl.strohalm.cyclos.services.elements.ElementService.changeMemberGroup(..)) && args(member, newGroup, comments)", argNames = "member, newGroup, comments") public Member removedFromBrokerGroupNotification(final ProceedingJoinPoint pjp, Member member, final MemberGroup newGroup, final String comments) throws Throwable { member = (Member) elementService.load(member.getId(), Element.Relationships.GROUP); final MemberGroup oldGroup = member.getMemberGroup(); member = (Member) pjp.proceed(); // Send message to the ex-broker that he is a now a normal member if (oldGroup.isBroker() && newGroup.getStatus() != Group.Status.REMOVED && !newGroup.isBroker()) { // Get message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getRemovedFromBrokerGroupSubject(); final String body = messageSettings.getRemovedFromBrokerGroupMessage(); final String sms = messageSettings.getRemovedFromBrokerGroupSms(); // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, newGroup, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, newGroup, localSettings); final String processedSms = MessageProcessingHelper.processVariables(sms, newGroup, localSettings); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.BROKERING); message.setToMember(member); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } // Send the return back to the caller return member; } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.PaymentService.processScheduled(..))", argNames = "transfer", returning = "transfer") public void scheduledPaymentProcessingAutomaticNotification(final Transfer transfer) { notifyScheduledPaymentProcessing(transfer, false); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.transactions.ScheduledPaymentService.processTransfer*(..))", argNames = "transfer", returning = "transfer") public void scheduledPaymentProcessingManualNotification(final Transfer transfer) { notifyScheduledPaymentProcessing(transfer, true); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.access.AccessService.changeMyPassword(..)) && args(params, remoteAddress)", argNames = "params, remoteAddress") public void changePassword(ChangeLoginPasswordDTO params, String remoteAddress) { if (params.getUser().getElement() instanceof Member) { sendChangePasswordMessage((Member) params.getUser().getElement()); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.access.AccessService.changeMemberCredentialsByWebService(..)) && args(memberUser, client, newCredentials)", argNames = "memberUser, client, newCredentials") public void changePasswordByWebService(MemberUser memberUser, ServiceClient client, String newCredentials) { sendChangePasswordMessage(memberUser.getMember()); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.access.AccessService.resetPasswordOnly(..)) && args(params)", argNames = "params") public void resetPasswordByAdmin(ChangeLoginPasswordDTO params) { changePasswordByAdmin(params); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.access.AccessService.changeMemberPassword(..)) && args(params)", argNames = "params") public void changePasswordByAdmin(ChangeLoginPasswordDTO params) { final MemberUser user = (MemberUser) fetchService.fetch(params.getUser(), RelationshipHelper.nested(User.Relationships.ELEMENT, Element.Relationships.GROUP)); Member member = user.getMember(); user.setLoginPassword(params.getNewPassword()); MessageSettings messageSettings = settingsService.getMessageSettings(); messageHelper().sendMemberMessage(messageSettings.getChangePasswordByAdminSubject(), messageSettings.getChangePasswordByAdminMessage(), messageSettings.getChangePasswordByAdminSms(), member, Message.Type.CHANGE_PASSWORD_BY_ADMIN, user); } public void setAccountService(final AccountService accountService) { this.accountService = accountService; } public void setBrokeringService(final BrokeringService brokeringService) { this.brokeringService = brokeringService; } public void setCertificationService(final CertificationService certificationService) { this.certificationService = certificationService; } public void setChannelService(final ChannelService channelService) { this.channelService = channelService; } public void setElementService(final ElementService elementService) { this.elementService = elementService; } public void setFetchService(final FetchService fetchService) { this.fetchService = fetchService; } public void setGroupService(final GroupService groupService) { this.groupService = groupService; } public void setInvoiceService(final InvoiceService invoiceService) { this.invoiceService = invoiceService; } public void setMessageResolver(final MessageResolver messageResolver) { this.messageResolver = messageResolver; } public void setMessageService(final MessageService messageService) { this.messageService = messageService; } public void setPaymentObligationService(final PaymentObligationService paymentObligationService) { this.paymentObligationService = paymentObligationService; } public void setPreferenceService(final PreferenceService preferenceService) { this.preferenceService = preferenceService; } public void setSettingsService(final SettingsService settingsService) { this.settingsService = settingsService; } public void setTicketService(final TicketService ticketService) { this.ticketService = ticketService; } public void setSmsSender(SmsSender smsSender) { this.smsSender = smsSender; } public void setTokenService(TokenService tokenService) { this.tokenService = tokenService; } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.ReferenceService.saveTransactionFeedbackByAdmin(..))", returning = "transactionFeedback", argNames = "transactionFeedback") public void transactionFeedBackAdminCommentsNotification(final TransactionFeedback transactionFeedback) { // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getTransactionFeedbackAdminCommentsSubject(); final String body = messageSettings.getTransactionFeedbackAdminCommentsMessage(); final String sms = messageSettings.getTransactionFeedbackAdminCommentsSms(); // Process message body final LocalSettings localSettings = settingsService.getLocalSettings(); // Send the notification to the feedback writer { final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, transactionFeedback.getTo(), transactionFeedback.getTransfer()); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, transactionFeedback.getTo(), transactionFeedback.getTransfer()); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, transactionFeedback.getTo(), transactionFeedback.getTransfer()); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.TRANSACTION_FEEDBACK); message.setEntity(transactionFeedback); message.setToMember(transactionFeedback.getFrom()); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } // Send the notification to the feedback receiver { final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, transactionFeedback.getFrom(), transactionFeedback.getTransfer()); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, transactionFeedback.getFrom(), transactionFeedback.getTransfer()); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.TRANSACTION_FEEDBACK); message.setEntity(transactionFeedback); message.setToMember(transactionFeedback.getTo()); message.setSubject(processedSubject); message.setBody(processedBody); // Send the message messageService.sendFromSystem(message); } } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.ReferenceService.saveTransactionFeedbackComments(..))", returning = "transactionFeedback", argNames = "transactionFeedback") public void transactionFeedBackReceivedNotification(final TransactionFeedback transactionFeedback) { // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getTransactionFeedbackReceivedSubject(); final String body = messageSettings.getTransactionFeedbackReceivedMessage(); final String sms = messageSettings.getTransactionFeedbackReceivedSms(); final LocalSettings localSettings = settingsService.getLocalSettings(); final Map<String, Object> extraVariables = new HashMap<String, Object>(); final Payment payment = transactionFeedback.getPayment(); final Calendar limit = payment.getType().getFeedbackReplyExpirationTime().add(Calendar.getInstance()); extraVariables.put("limit", localSettings.getDateConverter().toString(limit)); // Process the message String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, transactionFeedback.getFrom(), payment); processedSubject = MessageProcessingHelper.processVariables(processedSubject, extraVariables); String processedBody = MessageProcessingHelper.processVariables(body, localSettings, transactionFeedback.getFrom(), payment); processedBody = MessageProcessingHelper.processVariables(processedBody, extraVariables); String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, transactionFeedback.getFrom(), payment); processedSms = MessageProcessingHelper.processVariables(processedSms, extraVariables); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.TRANSACTION_FEEDBACK); message.setEntity(transactionFeedback); message.setToMember(transactionFeedback.getTo()); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } @AfterReturning(pointcut = "execution(* nl.strohalm.cyclos.services.elements.ReferenceService.saveTransactionFeedbackReplyComments(..))", returning = "transactionFeedback", argNames = "transactionFeedback") public void transactionFeedBackReplyNotification(final TransactionFeedback transactionFeedback) { // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getTransactionFeedbackReplySubject(); final String body = messageSettings.getTransactionFeedbackReplyMessage(); final String sms = messageSettings.getTransactionFeedbackReplySms(); // Process message body final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, transactionFeedback.getTo(), transactionFeedback.getTransfer()); final String processedBody = MessageProcessingHelper.processVariables(body, localSettings, transactionFeedback.getTo(), transactionFeedback.getTransfer()); final String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, transactionFeedback.getTo(), transactionFeedback.getTransfer()); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.TRANSACTION_FEEDBACK); message.setEntity(transactionFeedback); message.setToMember(transactionFeedback.getFrom()); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } private void certificationStatusChangedNotification(final Certification certification) { // Only notify if it's an activation or suspension, SHCEDULED is none of these if (certification.getStatus() == Certification.Status.SCHEDULED) { return; } // Get local and message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); // Process new status string final String statusString = messageResolver .message("certification.status." + certification.getStatus().toString()); final Map<String, Object> variables = certification.getVariableValues(localSettings); variables.put("status", statusString); // Get the destination (buyer) final Member buyer = certification.getBuyer(); // Get the message settings (buyer) final String subjectBuyer = messageSettings.getCertificationStatusChangedSubject(); final String bodyBuyer = messageSettings.getCertificationStatusChangedMessage(); final String smsBuyer = messageSettings.getCertificationStatusChangedSms(); // Process message content (buyer) final String processedSubjectBuyer = MessageProcessingHelper.processVariables(subjectBuyer, variables); final String processedBodyBuyer = MessageProcessingHelper.processVariables(bodyBuyer, variables); final String processedSmsBuyer = MessageProcessingHelper.processVariables(smsBuyer, variables); // Create the DTO (buyer) final SendMessageFromSystemDTO messageToBuyer = new SendMessageFromSystemDTO(); messageToBuyer.setEntity(certification); messageToBuyer.setType(Message.Type.CERTIFICATION); messageToBuyer.setToMember(buyer); messageToBuyer.setSubject(processedSubjectBuyer); messageToBuyer.setBody(processedBodyBuyer); messageToBuyer.setSms(processedSmsBuyer); // Send the message (to buyer) messageService.sendFromSystem(messageToBuyer); // If the new status is "EXPIRED" notify the issuer too if (certification.getStatus() == Certification.Status.EXPIRED) { // Get the destination (issuer) final Member issuer = certification.getIssuer(); // Get the message settings (issuer) final String subjectIssuer = messageSettings.getExpiredCertificationSubject(); final String bodyIssuer = messageSettings.getExpiredCertificationMessage(); final String smsIssuer = messageSettings.getExpiredCertificationSms(); // Process message content (issuer) final String processedSubjectIssuer = MessageProcessingHelper.processVariables(subjectIssuer, certification, localSettings); final String processedBodyIssuer = MessageProcessingHelper.processVariables(bodyIssuer, certification, localSettings); final String processedSmsIssuer = MessageProcessingHelper.processVariables(smsIssuer, certification, localSettings); // Create the DTO (issuer) final SendMessageFromSystemDTO messageToIssuer = new SendMessageFromSystemDTO(); messageToIssuer.setEntity(certification); messageToIssuer.setType(Message.Type.CERTIFICATION); messageToIssuer.setToMember(issuer); messageToIssuer.setSubject(processedSubjectIssuer); messageToIssuer.setBody(processedBodyIssuer); messageToIssuer.setSms(processedSmsIssuer); // Send the message (to buyer) messageService.sendFromSystem(messageToIssuer); } } private void doGuaranteeStatusChangedNotification(final Guarantee guarantee, final Guarantee.Status prevStatus) { // Get local and message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); // Process new status string final String statusString = messageResolver.message("guarantee.status." + guarantee.getStatus().toString()); final Map<String, Object> variables = guarantee.getVariableValues(localSettings); variables.put("status", statusString); final Guarantee.Status newStatus = guarantee.getStatus(); // If the guarantee was accepted, denied or cancelled, notify members if (newStatus == Guarantee.Status.ACCEPTED || newStatus == Guarantee.Status.REJECTED || newStatus == Guarantee.Status.CANCELLED) { // Check if the model of the guarantee is "buyer only" final boolean buyerOnly = guarantee.getGuaranteeType() .getModel() == GuaranteeType.Model.WITH_BUYER_ONLY; // Get the destination final Member buyer = guarantee.getBuyer(); final Member seller = guarantee.getSeller(); final Member issuer = guarantee.getIssuer(); // Get the message settings String subject = null; String body = null; String sms = null; if (buyerOnly) { subject = messageSettings.getBuyerOnlyGuaranteeStatusChangedSubject(); body = messageSettings.getBuyerOnlyGuaranteeStatusChangedMessage(); sms = messageSettings.getBuyerOnlyGuaranteeStatusChangedSms(); } else { subject = messageSettings.getGuaranteeStatusChangedSubject(); body = messageSettings.getGuaranteeStatusChangedMessage(); sms = messageSettings.getGuaranteeStatusChangedSms(); } // Process message content final String processedSubject = MessageProcessingHelper.processVariables(subject, variables); final String processedBody = MessageProcessingHelper.processVariables(body, variables); final String processedSms = MessageProcessingHelper.processVariables(sms, variables); // Create the message DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(guarantee); message.setType(Message.Type.GUARANTEE); // Send the message to the buyer message.setToMember(buyer); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); messageService.sendFromSystem(message); // If the guarantee was cancelled, notify the issuer too if (newStatus == Guarantee.Status.CANCELLED) { message.setToMember(issuer); message.setSubject(processedSubject); message.setBody(processedBody); messageService.sendFromSystem(message); } // If the model is not "buyer only", notify the seller too if (!buyerOnly) { message.setToMember(seller); message.setSubject(processedSubject); message.setBody(processedBody); messageService.sendFromSystem(message); } } else if (newStatus == Guarantee.Status.WITHOUT_ACTION && prevStatus == Guarantee.Status.PENDING_ISSUER) { // If the guarantee has expired, // Notify the issuer // Get the destination final Member issuer = guarantee.getIssuer(); // Get the message settings final String subject = messageSettings.getExpiredGuaranteeSubject(); final String body = messageSettings.getExpiredGuaranteeMessage(); final String sms = messageSettings.getExpiredGuaranteeSms(); // Process message content final String processedSubject = MessageProcessingHelper.processVariables(subject, variables); final String processedBody = MessageProcessingHelper.processVariables(body, variables); final String processedSms = MessageProcessingHelper.processVariables(sms, variables); // Create the message DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setEntity(guarantee); message.setType(Message.Type.GUARANTEE); message.setSubject(processedSubject); message.setBody(processedBody); message.setToMember(issuer); message.setSms(processedSms); // Send the message to the issuer messageService.sendFromSystem(message); } } /** * Notify the owner of the given account if it is getting low units. In a separated method as it need to be synchronized */ private synchronized void doSendLowUnitsNotification(final MemberAccount account, final MemberGroupAccountSettings mgas) { final Calendar currentDate = DateHelper.truncate(Calendar.getInstance()); if (lastPaymentDate == null || !lastPaymentDate.equals(currentDate)) { lastPaymentDate = currentDate; sentLowUnits.clear(); } final Member fromOwner = account.getOwner(); final BigDecimal lowUnits = mgas.getLowUnits() == null ? BigDecimal.ZERO : mgas.getLowUnits(); final BigDecimal availableBalance = accountService.getStatus(new GetTransactionsDTO(account)) .getAvailableBalance(); final BigDecimal creditLimit = account.getCreditLimit(); final Long memberId = fromOwner.getId(); // ... check if the balance is smaller than low units, and ... if (availableBalance.add(creditLimit.abs()).compareTo(lowUnits) != 1) { // ... send the personal message only once a day (controlled by the sentLowUnits set) if (!sentLowUnits.contains(memberId)) { // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getLowUnitsSubject(); final String body = messageSettings.getLowUnitsMessage(); final String sms = messageSettings.getLowUnitsSms(); // Process message content final LocalSettings localSettings = settingsService.getLocalSettings(); final UnitsConverter converter = localSettings .getUnitsConverter(account.getType().getCurrency().getPattern()); final Map<String, Object> variables = new HashMap<String, Object>(); variables.putAll(fromOwner.getVariableValues(localSettings)); variables.putAll(account.getVariableValues(localSettings)); variables.put("balance", converter.toString(availableBalance)); final String processedSubject = MessageProcessingHelper.processVariables(subject, variables); final String processedBody = MessageProcessingHelper.processVariables(body, variables); final String processedSms = MessageProcessingHelper.processVariables(sms, variables); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.ACCOUNT); message.setToMember(fromOwner); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); // Update table that controls duplicates sentLowUnits.add(memberId); } } else { sentLowUnits.remove(memberId); } } private void externalChannelPaymentNotification(final Payment payment, final Channel fromChannel, final Channel toChannel) { // Get local and message settings final LocalSettings localSettings = settingsService.getLocalSettings(); final MessageSettings messageSettings = settingsService.getMessageSettings(); final boolean isPaymentConfirmation = toChannel != null; final Channel smsChannel = channelService.getSmsChannel(); // if it isn't then is a payment from System if (payment.getFromOwner() instanceof Member) { final Channel channelToCheckForPayer = isPaymentConfirmation ? toChannel : fromChannel; final boolean skipSms = channelToCheckForPayer != null && channelToCheckForPayer.equals(smsChannel); // Get the origin final Member fromMember = (Member) payment.getFromOwner(); // Get the message settings final String subject = messageSettings.getExternalChannelPaymentPerformedSubject(); final String body = messageSettings.getExternalChannelPaymentPerformedMessage(); final String sms = skipSms ? null : messageSettings.getExternalChannelPaymentPerformedSms(); // Process message content final Map<String, Object> variableValues = payment.getVariableValues(localSettings); variableValues.put("channel", channelToCheckForPayer.getDisplayName()); final AccountOwner toOwner = payment.getToOwner(); String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, toOwner, payment); processedSubject = MessageProcessingHelper.processVariables(processedSubject, variableValues); String processedBody = MessageProcessingHelper.processVariables(body, localSettings, toOwner, payment); processedBody = MessageProcessingHelper.processVariables(processedBody, variableValues); String processedSms = null; if (sms != null) { processedSms = MessageProcessingHelper.processVariables(sms, localSettings, toOwner, payment); processedSms = MessageProcessingHelper.processVariables(processedSms, variableValues); } // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setToMember(fromMember); message.setType(Message.Type.EXTERNAL_PAYMENT); message.setEntity(payment); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } // Now, notify the member that received the payment, only if not to channel is SMS final Channel channelToCheckForReceiver = isPaymentConfirmation ? fromChannel : toChannel; if (channelToCheckForReceiver == null || !channelToCheckForReceiver.equals(smsChannel)) { paymentReceivedNotification(payment); } } /** * Send the low units notification if needed */ private void notifyLowUnits(final Payment payment) { if (!(payment instanceof Transfer)) { return; } final Account account = fetchService.fetch(payment.getFrom(), RelationshipHelper.nested(Account.Relationships.TYPE, AccountType.Relationships.CURRENCY), RelationshipHelper.nested(Transfer.Relationships.FROM, MemberAccount.Relationships.MEMBER, Element.Relationships.GROUP)); if (!(account instanceof MemberAccount)) { return; } final MemberAccount memberAccount = (MemberAccount) account; final Group group = memberAccount.getMember().getGroup(); final AccountType accountType = account.getType(); final MemberGroupAccountSettings mgas = groupService.loadAccountSettings(group.getId(), accountType.getId()); final BigDecimal lowUnits = mgas.getLowUnits() == null ? BigDecimal.ZERO : mgas.getLowUnits(); // If low units message is used... if (lowUnits.floatValue() > PRECISION_DELTA && StringUtils.isNotEmpty(mgas.getLowUnitsMessage())) { doSendLowUnitsNotification(memberAccount, mgas); } } private void notifyScheduledPaymentProcessing(final Transfer transfer, final boolean manual) { // Get the required data final Member payer = transfer.isFromSystem() ? null : (Member) transfer.getFrom().getOwner(); final Member payee = transfer.isToSystem() ? null : (Member) transfer.getTo().getOwner(); final Authorizer authorizer = getAuthorizer(transfer); final MessageSettings messageSettings = settingsService.getMessageSettings(); // Resolve the message String payerSubject; String payerBody; String payerSms; String payeeSubject; String payeeBody; String payeeSms; switch (transfer.getStatus()) { case PROCESSED: // Don't notify the payer when he manually pays if (manual) { payerSubject = null; payerBody = null; payerSms = null; } else { payerSubject = messageSettings.getScheduledPaymentProcessedSubject(); payerBody = messageSettings.getScheduledPaymentProcessedMessage(); payerSms = messageSettings.getScheduledPaymentProcessedSms(); } payeeSubject = messageSettings.getPaymentReceivedSubject(); payeeBody = messageSettings.getPaymentReceivedMessage(); payeeSms = messageSettings.getPaymentReceivedSms(); break; case PENDING: // Payer don't get notified payerSubject = null; payerBody = null; payerSms = null; // Check whether the payee should authorize if (authorizer == Authorizer.RECEIVER) { payeeSubject = messageSettings.getNewPendingPaymentByReceiverSubject(); payeeBody = messageSettings.getNewPendingPaymentByReceiverMessage(); payeeSms = messageSettings.getNewPendingPaymentByReceiverSms(); } else { payeeSubject = messageSettings.getPendingPaymentReceivedSubject(); payeeBody = messageSettings.getPendingPaymentReceivedMessage(); payeeSms = messageSettings.getPendingPaymentReceivedSms(); } break; case FAILED: payerSubject = messageSettings.getScheduledPaymentFailedToPayerSubject(); payerBody = messageSettings.getScheduledPaymentFailedToPayerMessage(); payerSms = messageSettings.getScheduledPaymentFailedToPayerSms(); try { final ScheduledPayment scheduledPayment = transfer.getScheduledPayment(); invoiceService.loadByPayment(scheduledPayment == null ? transfer : scheduledPayment); payeeSubject = messageSettings.getScheduledPaymentFailedToPayeeSubject(); payeeBody = messageSettings.getScheduledPaymentFailedToPayeeMessage(); payeeSms = messageSettings.getScheduledPaymentFailedToPayeeSms(); } catch (final EntityNotFoundException e) { // Don't send message to payee when there's no associated invoice payeeSubject = null; payeeBody = null; payeeSms = null; } break; default: // Unknown status here!!! return; } // Prepare the message final LocalSettings localSettings = settingsService.getLocalSettings(); SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.PAYMENT); message.setEntity(transfer); // Send the message to the payer final Set<MessageChannel> payerChannels = payer == null || payerSubject == null ? null : preferenceService.receivedChannels(payer, Message.Type.PAYMENT); if (CollectionUtils.isNotEmpty(payerChannels)) { AccountStatus statusPayer = null; final boolean sendSmsNotification = transfer.getType().isAllowSmsNotification() && payerChannels.contains(MessageChannel.SMS); if (sendSmsNotification) { statusPayer = accountService.getStatus(new GetTransactionsDTO(transfer.getFrom())); } final AccountOwner payeeOwner = payee == null ? SystemAccountOwner.instance() : payee; message.setToMember(payer); message.setSubject( MessageProcessingHelper.processVariables(payerSubject, localSettings, payeeOwner, transfer)); message.setBody( MessageProcessingHelper.processVariables(payerBody, localSettings, payeeOwner, transfer)); if (sendSmsNotification) { message.setSms(MessageProcessingHelper.processVariables(payerSms, localSettings, payeeOwner, transfer, statusPayer)); } messageService.sendFromSystem(message); } // Send the message to the payee final Set<MessageChannel> payeeChannels = payee == null || payeeSubject == null ? null : preferenceService.receivedChannels(payee, Message.Type.PAYMENT); if (CollectionUtils.isNotEmpty(payeeChannels)) { AccountStatus statusPayee = null; final boolean sendSmsNotification = transfer.getType().isAllowSmsNotification() && payeeChannels.contains(MessageChannel.SMS); if (sendSmsNotification) { statusPayee = accountService.getStatus(new GetTransactionsDTO(transfer.getTo())); } final AccountOwner payerOwner = payer == null ? SystemAccountOwner.instance() : payer; message.setToMember(payee); message.setSubject( MessageProcessingHelper.processVariables(payeeSubject, localSettings, payerOwner, transfer)); message.setBody( MessageProcessingHelper.processVariables(payeeBody, localSettings, payerOwner, transfer)); if (sendSmsNotification) { message.setSms(MessageProcessingHelper.processVariables(payeeSms, localSettings, payerOwner, transfer, statusPayee)); } messageService.sendFromSystem(message); } // Notify the broker final Member broker = payer == null ? null : payer.getBroker(); if (authorizer == Authorizer.BROKER && broker != null) { final String subject = messageSettings.getNewPendingPaymentByBrokerSubject(); final String body = messageSettings.getNewPendingPaymentByBrokerMessage(); final String sms = messageSettings.getNewPendingPaymentByBrokerSms(); // Send the message message = new SendMessageFromSystemDTO(); message.setType(Message.Type.BROKERING); message.setEntity(transfer); message.setToMember(broker); message.setSubject(MessageProcessingHelper.processVariables(subject, localSettings, payer, transfer)); message.setBody(MessageProcessingHelper.processVariables(body, localSettings, payer, transfer)); message.setSms(MessageProcessingHelper.processVariables(sms, localSettings, payer, transfer)); messageService.sendFromSystem(message); } // Send a low units notification, if needed notifyLowUnits(transfer); } private void notifyTransactionFeedbackRequest(Payment payment) { // Payments from/to system, that hasn't been authorized yet or that don't use feedbacks are not notified payment = fetchService.fetch(payment, Transfer.Relationships.FROM, Transfer.Relationships.TO, Transfer.Relationships.TYPE); if (payment == null || payment.isFromSystem() || payment.isToSystem() || !payment.getType().isRequiresFeedback()) { return; } // Transfers without process dates are skipped too if (payment instanceof Transfer) { final Transfer transfer = (Transfer) payment; if (transfer.getProcessDate() == null) { return; } } final Member from = (Member) payment.getFromOwner(); final Member to = (Member) payment.getToOwner(); // Get the message settings final MessageSettings messageSettings = settingsService.getMessageSettings(); final String subject = messageSettings.getTransactionFeedbackRequestSubject(); final String body = messageSettings.getTransactionFeedbackRequestMessage(); final String sms = messageSettings.getTransactionFeedbackRequestSms(); // Process message body final LocalSettings localSettings = settingsService.getLocalSettings(); final Map<String, Object> extraVariables = new HashMap<String, Object>(); final Calendar limit = payment.getType().getFeedbackExpirationTime().add(Calendar.getInstance()); extraVariables.put("limit", localSettings.getDateConverter().toString(limit)); String processedSubject = MessageProcessingHelper.processVariables(subject, localSettings, to, payment); String processedBody = MessageProcessingHelper.processVariables(body, localSettings, to, payment); String processedSms = MessageProcessingHelper.processVariables(sms, localSettings, to, payment); processedSubject = MessageProcessingHelper.processVariables(processedSubject, extraVariables); processedBody = MessageProcessingHelper.processVariables(processedBody, extraVariables); processedSms = MessageProcessingHelper.processVariables(processedSms, extraVariables); // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.TRANSACTION_FEEDBACK); message.setEntity(new TransactionFeedbackRequest(payment)); message.setToMember(from); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } private void sendPaymentMessages(final Transfer transfer, final List<Member> sendMessageTo, final String subject, final String body, final String sms) { // Process message contents final LocalSettings localSettings = settingsService.getLocalSettings(); final String processedSubject = MessageProcessingHelper.processVariables(subject, transfer, localSettings); final String processedBody = MessageProcessingHelper.processVariables(body, transfer, localSettings); final String processedSms = transfer.getType().isAllowSmsNotification() ? MessageProcessingHelper.processVariables(sms, transfer, localSettings) : null; // Send each message for (final Member member : sendMessageTo) { // Create the DTO final SendMessageFromSystemDTO message = new SendMessageFromSystemDTO(); message.setType(Message.Type.PAYMENT); message.setEntity(transfer); message.setToMember(member); message.setSubject(processedSubject); message.setBody(processedBody); message.setSms(processedSms); // Send the message messageService.sendFromSystem(message); } } private void sendRegistrationMessage(Member member) { MessageSettings messageSettings = settingsService.getMessageSettings(); messageHelper().sendMemberMessage(messageSettings.getRegisteredSubject(), messageSettings.getRegisteredMessage(), messageSettings.getRegisteredSms(), member, Message.Type.REGISTRATION); } private void sendChangePasswordMessage(Member member) { MessageSettings messageSettings = settingsService.getMessageSettings(); messageHelper().sendMemberMessage(messageSettings.getChangePasswordSubject(), messageSettings.getChangePasswordMessage(), messageSettings.getChangePasswordSms(), member, Message.Type.CHANGE_PASSWORD); } MessageHelper messageHelper() { if (messageHelper == null) { messageHelper = new MessageHelper(settingsService, messageService); } return messageHelper; } TokenMessages tokenMessages() { if (tokenMessages == null) { tokenMessages = new TokenMessages(settingsService, smsSender, messageService, accountService); } return tokenMessages; } }