Subversion Repositories SmartDukaan

Rev

Rev 37388 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 37388 Rev 37409
Line 1... Line 1...
1
package com.spice.profitmandi.service;
1
package com.spice.profitmandi.service;
2
 
2
 
3
import com.google.gson.Gson;
3
import com.google.gson.Gson;
4
import com.spice.profitmandi.common.enumuration.MessageType;
4
import com.spice.profitmandi.common.enumuration.MessageType;
5
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
5
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
-
 
6
import com.spice.profitmandi.common.model.CustomRetailer;
6
import com.spice.profitmandi.common.model.ProfitMandiConstants;
7
import com.spice.profitmandi.common.model.ProfitMandiConstants;
7
import com.spice.profitmandi.common.model.SendNotificationModel;
8
import com.spice.profitmandi.common.model.SendNotificationModel;
8
import com.spice.profitmandi.dao.entity.auth.AuthUser;
9
import com.spice.profitmandi.dao.entity.auth.AuthUser;
9
import com.spice.profitmandi.dao.entity.dtr.*;
10
import com.spice.profitmandi.dao.entity.dtr.*;
10
import com.spice.profitmandi.dao.entity.fofo.Customer;
11
import com.spice.profitmandi.dao.entity.fofo.Customer;
Line 21... Line 22...
21
import com.spice.profitmandi.service.user.RetailerService;
22
import com.spice.profitmandi.service.user.RetailerService;
22
import com.spice.profitmandi.service.whatsapp.WhatsappFlow;
23
import com.spice.profitmandi.service.whatsapp.WhatsappFlow;
23
import com.spice.profitmandi.service.whatsapp.WhatsappMessageService;
24
import com.spice.profitmandi.service.whatsapp.WhatsappMessageService;
24
import com.spice.profitmandi.service.whatsapp.WhatsappMessageType;
25
import com.spice.profitmandi.service.whatsapp.WhatsappMessageType;
25
import com.spice.profitmandi.service.whatsapp.WhatsappNumbers;
26
import com.spice.profitmandi.service.whatsapp.WhatsappNumbers;
26
import com.spice.profitmandi.service.whatsapp.WhatsappProviderResolver;
27
import com.spice.profitmandi.service.whatsapp.BotPenguinWhatsappService;
27
import org.apache.logging.log4j.LogManager;
28
import org.apache.logging.log4j.LogManager;
28
import org.apache.logging.log4j.Logger;
29
import org.apache.logging.log4j.Logger;
29
import org.springframework.beans.factory.annotation.Autowired;
30
import org.springframework.beans.factory.annotation.Autowired;
30
import org.springframework.beans.factory.annotation.Value;
31
import org.springframework.beans.factory.annotation.Value;
31
import org.springframework.stereotype.Component;
32
import org.springframework.stereotype.Component;
Line 80... Line 81...
80
 
81
 
81
    @Autowired
82
    @Autowired
82
    private WhatsappMessageService whatsappMessageService;
83
    private WhatsappMessageService whatsappMessageService;
83
 
84
 
84
    @Autowired
85
    @Autowired
85
    private WhatsappProviderResolver whatsappProviders;
86
    private BotPenguinWhatsappService botPenguin;
86
 
87
 
87
    @Override
88
    @Override
88
    public void sendNotification(SendNotificationModel sendNotificationModel) throws ProfitMandiBusinessException {
89
    public void sendNotification(SendNotificationModel sendNotificationModel) throws ProfitMandiBusinessException {
89
 
90
 
90
        SimpleCampaignParams scp = new SimpleCampaignParams();
91
        SimpleCampaignParams scp = new SimpleCampaignParams();
Line 225... Line 226...
225
        sendNotificationModel.setMessageType(messageType);
226
        sendNotificationModel.setMessageType(messageType);
226
        sendNotificationModel.setUrl(url);
227
        sendNotificationModel.setUrl(url);
227
        this.sendNotification(sendNotificationModel);
228
        this.sendNotification(sendNotificationModel);
228
    }
229
    }
229
 
230
 
230
    @Override
-
 
231
    public boolean sendWhatsappMessage(String message, String title, String mobile) throws Exception {
-
 
232
        boolean isSend=false;
-
 
233
        LOGGER.info("Is Prod - {}", isProd);
-
 
234
        if (isProd) {
-
 
235
            isSend=this.sendWhatsappMessage(WhatsappFlow.GENERIC, WhatsappMessageType.TEXT, message, title, mobile, null, null);
-
 
236
        }
231
    /**
237
        return isSend;
232
     * Invoice PDF, sent as the template's document header.
238
    }
233
     *
239
 
-
 
240
    @Override
-
 
241
    public void sendADLDWhatsappMessage(String mobile) throws Exception {
234
     * <p>The upsell wording that used to be built here now lives in the approved template; only the
242
        LOGGER.info("Is Prod - {}", isProd);
-
 
243
        if (isProd) {
-
 
244
            String message = "क्या आपने SmartDukaan Protect Plus Plan लिया है?\n\n" +
-
 
245
                    "सिर्फ ₹199 से शुरू, पाएं अपने मोबाइल के लिए 1 साल की स्मार्ट सुरक्षा —\n" +
-
 
246
                    "Liquid Damage Protection\n" +
-
 
247
                    "Accidental Damage Protection\n" +
235
     * recipient's name and the PDF link cross the wire.</p>
248
                    "अपने फोन को महंगे रिपेयर खर्च से बचाएं।\n" +
-
 
249
                    "अभी जानकारी लें और अपने फोन को सुरक्षित बनाएं!";
-
 
250
            String title = "SmartDukaan से खरीदारी करने के लिए धन्यवाद!";
-
 
251
 
-
 
252
            this.sendWhatsappMessage(WhatsappFlow.ADLD, WhatsappMessageType.TEXT, message, title, mobile, null, null);
-
 
253
        }
-
 
254
    }
236
     */
255
 
-
 
256
    @Override
237
    @Override
257
    public boolean sendWhatsappInvoice(int customerId, int fofoId, String invoiceNumber, String whatsAppNo) throws Exception {
238
    public boolean sendWhatsappInvoice(int customerId, int fofoId, String invoiceNumber, String whatsAppNo) throws Exception {
258
        boolean shouldSend = shouldSendWhatsappMessage(whatsAppNo);
239
        if (!shouldSendWhatsappMessage(whatsAppNo)) {
259
        if (!shouldSend) return false;
240
            return false;
260
 
241
        }
261
        Customer customer = customerRepository.selectById(customerId);
242
        Customer customer = customerRepository.selectById(customerId);
262
        String mobileNumber = (whatsAppNo != null && !whatsAppNo.isEmpty()) ? whatsAppNo : customer.getMobileNumber();
243
        String mobileNumber = (whatsAppNo != null && !whatsAppNo.isEmpty()) ? whatsAppNo : customer.getMobileNumber();
263
 
244
 
264
        String message = "*SmartDukaan's One-Time Offer Unlocked!*\n" +
-
 
265
                "Thank you for your purchase.\n" +
-
 
266
                "\n" +
-
 
267
                "Abhi-abhi naya phone liya hai...\n" +
-
 
268
                "Par kya aapne uski poori suraksha li hai?\n" +
-
 
269
                "SmartDukaan par sabse kam daam mein plans available hain:\n" +
-
 
270
                "\n" +
-
 
271
                "*Complete Protection Plan* (Accidental & Liquid Damage) - Starting ₹199\n" +
-
 
272
                "\n" +
-
 
273
                "*Extended 1 Year Warranty* - ₹199 se shuru\n" +
-
 
274
                "\n" +
-
 
275
                "Abhi store par iski jaankari lein.\n" +
-
 
276
                "\n" +
-
 
277
                "*Ye offer phone ki kharidari ke sirf 24 hours tak hi valid hai!*";
-
 
278
 
-
 
279
        String mediaUrl = "https://partners.smartdukaan.com/wa-invoice-send/"
245
        String mediaUrl = "https://partners.smartdukaan.com/wa-invoice-send/"
280
                + Base64.getMimeEncoder().encodeToString(invoiceNumber.getBytes(StandardCharsets.UTF_8)) + ".pdf";
246
                + Base64.getMimeEncoder().encodeToString(invoiceNumber.getBytes(StandardCharsets.UTF_8)) + ".pdf";
281
        String fileName = "INV-" + invoiceNumber.replace("/", "-") + ".pdf";
247
        String fileName = "INV-" + invoiceNumber.replace("/", "-") + ".pdf";
282
 
248
 
283
        LOGGER.info("sendWhatsappInvoice: mobile={} mediaUrl={}", mobileNumber, mediaUrl);
249
        LOGGER.info("sendWhatsappInvoice: mobile={} mediaUrl={}", mobileNumber, mediaUrl);
284
        // Goes straight to the provider rather than through sendWhatsappMediaMessage so the INVOICE flow
250
        return botPenguin.send(WhatsappFlow.INVOICE, mobileNumber,
285
        // is named: a template-first provider needs it to pick the approved invoice template.
251
                Arrays.asList(customerName(customer), storeName(fofoId)), mediaUrl, fileName,
286
        return this.sendWhatsappMessage(WhatsappFlow.INVOICE, WhatsappMessageType.DOCUMENT, message, null,
-
 
287
                mobileNumber, mediaUrl, fileName);
252
                WhatsappMessageType.DOCUMENT);
288
    }
253
    }
289
 
254
 
290
    @Override
255
    @Override
291
    public boolean sendWhatsappMediaMessage(String message, String mobile, String mediaUrl, String fileName, WhatsappMessageType whatsappMessageType) throws Exception {
256
    public boolean sendPaymentLink(String mobile, String paymentLink) throws Exception {
292
        boolean isSend=false;
257
        return botPenguin.send(WhatsappFlow.PAYMENT_LINK, mobile,
293
//        if (isProd) {
-
 
294
//            isSend=this.sendWhatsappMessage(whatsappMessageType, message, null, mobile, mediaUrl, fileName);
258
                Collections.singletonList(paymentLink), null, null, null);
295
//        }
259
    }
-
 
260
 
-
 
261
    @Override
-
 
262
    public boolean sendOfferAnnouncement(String mobile, String offerName, String schemeType, String startDate,
-
 
263
                                         String endDate, String imageUrl) throws Exception {
-
 
264
        return botPenguin.send(WhatsappFlow.OFFER, mobile,
296
        isSend = this.sendWhatsappMessage(WhatsappFlow.GENERIC, whatsappMessageType, message, null, mobile, mediaUrl, fileName);
265
                Arrays.asList(offerName, schemeType, startDate, endDate), imageUrl, null,
297
        return isSend;
266
                WhatsappMessageType.IMAGE);
298
    }
267
    }
299
 
268
 
300
    /**
-
 
301
     * Kept on this interface because cron calls it directly; it delegates to the active provider and is
-
 
302
     * a no-op for providers with no opt-in concept.
-
 
303
     */
-
 
304
    @Override
269
    @Override
305
    public void optIn(String phoneNumber) throws Exception {
270
    public boolean sendBiddingLive(String mobile, List<String> lots, String mediaUrl) throws Exception {
-
 
271
        int slots = ProfitMandiConstants.WHATSAPP_TEMPLATE.BIDDING_LIVE.getBodyParamCount();
-
 
272
        if (lots.size() > slots) {
-
 
273
            LOGGER.warn("sendBiddingLive: {} lots available but the template holds {}; dropping {}",
-
 
274
                    lots.size(), slots, lots.subList(slots, lots.size()));
-
 
275
        }
-
 
276
        List<String> params = new ArrayList<>(lots.subList(0, Math.min(lots.size(), slots)));
-
 
277
        // Meta rejects an empty parameter, so unused slots carry a dash rather than "".
306
        whatsappProviders.active().optIn(phoneNumber);
278
        while (params.size() < slots) {
-
 
279
            params.add("-");
-
 
280
        }
-
 
281
        return botPenguin.send(WhatsappFlow.BIDDING_LIVE, mobile, params, mediaUrl, null,
-
 
282
                WhatsappMessageType.IMAGE);
307
    }
283
    }
308
 
284
 
-
 
285
    @Override
-
 
286
    public boolean sendLoanDefaultAlert(String mobile, String name, String outstandingAmount) throws Exception {
-
 
287
        LOGGER.info("Is Prod - {}", isProd);
-
 
288
        if (!isProd) {
-
 
289
            return false;
-
 
290
        }
-
 
291
        return botPenguin.send(WhatsappFlow.LOAN_ALERT, mobile,
-
 
292
                Arrays.asList(name, outstandingAmount), null, null, null);
-
 
293
    }
-
 
294
 
-
 
295
    @Override
-
 
296
    public boolean sendOrderDelivered(String mobile, String airwayBillNumber) throws Exception {
-
 
297
        LOGGER.info("Is Prod - {}", isProd);
-
 
298
        if (!isProd) {
-
 
299
            return false;
-
 
300
        }
-
 
301
        return botPenguin.send(WhatsappFlow.ORDER_DELIVERED, mobile,
-
 
302
                Collections.singletonList(airwayBillNumber), null, null, null);
-
 
303
    }
-
 
304
 
-
 
305
    @Override
309
    private boolean sendWhatsappMessage(WhatsappFlow flow, WhatsappMessageType whatsappMessageType, String message,
306
    public boolean sendADLDWhatsappMessage(String mobile, String invoiceNumber, String mediaUrl,
310
                                        String title, String mobile, String mediaUrl, String fileName)
307
                                           String fileName) throws Exception {
-
 
308
        LOGGER.info("Is Prod - {}", isProd);
311
            throws Exception {
309
        if (!isProd) {
312
        return whatsappProviders.active()
310
            return false;
-
 
311
        }
313
                .sendBasic(flow, whatsappMessageType, message, title, mobile, mediaUrl, fileName);
312
        return botPenguin.send(WhatsappFlow.ADLD, mobile, Collections.singletonList(invoiceNumber),
-
 
313
                mediaUrl, fileName, WhatsappMessageType.DOCUMENT);
314
    }
314
    }
315
 
315
 
316
    @Override
316
    @Override
317
    public boolean shouldSendWhatsappMessage(String mobile) {
317
    public boolean shouldSendWhatsappMessage(String mobile) {
318
        // Normalised rather than concatenated: cpass and BotPenguin store the normalised MSISDN, so for
318
        // Normalised rather than concatenated: BotPenguin stores the normalised MSISDN, so for anything
319
        // anything that is not already a bare ten digits the old "91" + mobile key could never match a
319
        // that is not already a bare ten digits the old "91" + mobile key could never match a stored row
320
        // stored row and the throttle quietly never fired. Identical result for clean input.
320
        // and the throttle quietly never fired. Identical result for clean input.
321
        String destAddr = WhatsappNumbers.toMsisdn(mobile);
321
        String destAddr = WhatsappNumbers.toMsisdn(mobile);
322
        if (destAddr == null) {
322
        if (destAddr == null) {
323
            return true;
323
            return true;
324
        }
324
        }
325
        boolean shouldSend = true;
325
        boolean shouldSend = true;
Line 331... Line 331...
331
            }
331
            }
332
        }
332
        }
333
        return shouldSend;
333
        return shouldSend;
334
    }
334
    }
335
 
335
 
-
 
336
    /**
-
 
337
     * The store the purchase was made at, for the invoice template's second variable. Falls back to the
-
 
338
     * brand name: an unknown partner id must not stop an invoice going out.
-
 
339
     */
-
 
340
    private String storeName(int fofoId) {
-
 
341
        try {
-
 
342
            CustomRetailer retailer = retailerService.getFofoRetailer(fofoId);
-
 
343
            String businessName = retailer == null ? null : retailer.getBusinessName();
-
 
344
            if (businessName != null && !businessName.trim().isEmpty()) {
-
 
345
                return businessName.trim();
-
 
346
            }
-
 
347
        } catch (Exception e) {
-
 
348
            LOGGER.warn("storeName: could not resolve fofoId {}", fofoId, e);
-
 
349
        }
-
 
350
        return "SmartDukaan";
-
 
351
    }
336
 
352
 
-
 
353
    /** Meta greets by name, so an empty first name would render "Hello ,". */
337
    @Override
354
    private static String customerName(Customer customer) {
338
    public void sendPaymentWhatsappMessage(String mobile, String message) throws Exception {
355
        String firstName = customer == null ? null : customer.getFirstName();
339
        whatsappProviders.active().sendText(WhatsappFlow.PAYMENT_LINK, mobile, message);
356
        return (firstName == null || firstName.trim().isEmpty()) ? "Customer" : firstName.trim();
340
    }
357
    }
341
 
358
 
342
}
359
}