bank/MCM.class.js

const ScraperBank = require("../BrowserClasses");
const MANDIRISelector = require("../helper/selector/MANDIRISelector");
const log = require("../helper/utils/Logger");

/**
 * Kopra class for scraping Mandiri (Bank Mandiri) data.
 * @class
 * @extends ScraperBank
 * @memberof Bank
 */
class Kopra extends ScraperBank {
  /**
   * Constructor for Kopra class.
   * @constructor
   * @param {string} corpID - Mandiri corporate ID.
   * @param {string} user - Mandiri username.
   * @param {string} password - Mandiri password.
   * @param {string} noacc - Mandiri account number.
   * @param {boolean} useFingerprintInjector - Flag to use fingerprint injector.
   */
  constructor(corpID, user, password, noacc,useFingerprintInjector) {
    super(user, password,useFingerprintInjector);
    this.corpID = corpID;
    this.username = user;
    this.password = password;
    this.noacc = noacc;
    this.log = log;
  }


  /**
   * Gets the account statement from the Mandiri website.
   * @async
   * @returns {Object} - Result containing a message and data.
   */
  async getStatement() {
    this.log("login sebagai");

    const page = await this.launchBrowser();
    const browser = await page.browser();
    try {
      await page.goto(MANDIRISelector.LOGIN_PAGE.url, {
        waitUntil: "networkidle2",
      });
      await page.setViewport({ width: 1366, height: 768 });

      this.log("Mengarah ke login page..");
      await page.waitForSelector(MANDIRISelector.LOGIN_PAGE.corpIdInput);
      await page.type(MANDIRISelector.LOGIN_PAGE.corpIdInput, this.corpID, {
        delay: 100,
      });
      await page.type(MANDIRISelector.LOGIN_PAGE.userInput, this.username, {
        delay: 100,
      });
      await page.type(MANDIRISelector.LOGIN_PAGE.passInput, this.password, {
        delay: 100,
      });
      await page.click(MANDIRISelector.LOGIN_PAGE.submitButton, { delay: 200 });

      this.log("Menunggu response dari API");
      await page.click(MANDIRISelector.LOGIN_PAGE.submitButton, { delay: 200 });

      // Check for error message
      await page.waitForTimeout(2000);

      // Check for error message using XPath
      const errorMessageElements = await page.$x(
        MANDIRISelector.LOGIN_PAGE.error_message
      );

      if (errorMessageElements.length > 0) {
        throw new Error("Login failed. User still logged in.");
      }



      await page.waitForXPath(MANDIRISelector.DASHBOARD_PAGE.navbar); // nav selector
      await (await page.$x(MANDIRISelector.DASHBOARD_PAGE.navbar))[0]?.click();

      await (
        await page.$x(MANDIRISelector.DASHBOARD_PAGE.statementLink)
      )[0]?.click();

      await page.waitForNavigation();

      await page.waitForSelector(MANDIRISelector.STATEMENT_PAGE.dropdown);

      // Click the dropdown to open the options

      await page.waitForTimeout(3000);
      await page.click(MANDIRISelector.STATEMENT_PAGE.dropdown);
      await page.waitForTimeout(3000);
      const searchText = this.noacc;
      const targetElement = await page.waitForXPath(
        `${MANDIRISelector.STATEMENT_PAGE.norek}, '${searchText}')]`
      );
      await page.select(MANDIRISelector.STATEMENT_PAGE.statement_day, "today");

      // Click on the element containing the text
      await targetElement.click();
      await page.waitForSelector(
        MANDIRISelector.STATEMENT_PAGE.submit_statement
      );
      await page.click(MANDIRISelector.STATEMENT_PAGE.submit_statement);
      await page.waitForSelector(MANDIRISelector.STATEMENT_PAGE.nav_log);

      let jsonData;

      page.on("response", async (response) => {
        const request = response.request();
        const requestUrl = request.url();

        if (
          requestUrl ===
          "https://mcm2.bankmandiri.co.id/corporate/secure/widgets/accountOverview/getAccountStatement"
        ) {
          console.log("Response URL:", requestUrl);

          jsonData = await response.json();
        }
      });

      //console.log(jsonDataFromFile);
      await page.waitForSelector(MANDIRISelector.LOGOUT_PAGE.nav_logout);
      await page.click(MANDIRISelector.LOGOUT_PAGE.button_logout, {
        delay: 1000,
      });
      await page.waitForTimeout(1000);
      await browser.close();
      const data = jsonData.details.map(this.formatTransactionData);
      return {
        message : "success get data",
        data : data
      }
    } catch (error) {
      await browser.close();
      return {
        message : "Login failed. User still logged in",
        data : null
      }
      
    }
  }

  /**
   * Formats transaction data received from the Mandiri website.
   * @param {Object} transaction - Raw transaction data.
   * @returns {Object} - Formatted transaction data.
   */
   formatTransactionData(transaction) {
    try {
      const postingDate = new Date(transaction.gatewayPostingDate);
      const formattedDate = formatDate(postingDate);
      return {
        tanggal: formattedDate,
        date: formattedDate,
        deskripsi: transaction.remarks.trim().replace(/\.{2,}/g, ''),
        name: getName(transaction.remarks),
        type: transaction.debitAmount === "0" ? "kredit" : "debit",
        nominal: transaction.debitAmount === "0" ? transaction.creditAmount : transaction.debitAmount
      };
    } catch (error) {
      console.log(`Error formatting transaction data: ${error}`);
    }
  }

  /**
   * Formats a date object to a string.
   * @param {Date} date - Date object to be formatted.
   * @returns {string} - Formatted date string.
   */  
  formatDate(date) {
    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
      2,
      "0"
    )}-${String(date.getDate()).padStart(2, "0")} ${String(
      date.getHours()
    ).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}:${String(
      date.getSeconds()
    ).padStart(2, "0")}`;
  }
}

module.exports = Kopra;