Print Slip & IntranetUserJS

QUICK Slip

<head> 
  <link href="https://fonts.googleapis.com/css2?family=Libre+Barcode+39&display=swap" rel="stylesheet" />
  <style>
    @page {
      size: 5in auto; /* Increased page width */
      margin: 0.5in 0.3in 0.3in 0.3in;
    }

    body {
      margin: 0;
      padding: 0;
      font-family: Arial, sans-serif;
    }

    .right-side {
      width: 100%;
      max-width: 420px;
      margin-left: auto;
      font-weight: bold; /* All text bold by default */
      font-size: 22px;    /* Larger text */
    }

    table {
      width: 100%;
      border-collapse: collapse;
      table-layout: fixed;
      min-width: 400px;
    }

    td:first-child {
      width: 55%;
      text-align: left;
      white-space: normal;
      overflow: visible;
      padding: 4px 8px 4px 32px; /* Shift left text 4 spaces (approx) */
    }

    td:last-child {
      width: 45%;
      text-align: right;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      padding: 4px 8px;
    }

    tr.fax-row td:last-child {
      white-space: normal;
      overflow-wrap: break-word;
      max-width: 100%;
      padding-top: 8px;
      padding-bottom: 8px;
      font-size: 20px;
    }

    tr.firstname-row td:last-child {
      padding: 0;
      width: 45%;
      white-space: nowrap;
    }

    .barcode-container {
      width: 100%;
      text-align: center;
      margin-top: 15px;
    }

    .barcode {
      font-family: 'Libre Barcode 39', monospace;
      font-size: 40px;
      letter-spacing: 3px;
      white-space: nowrap;
      display: inline-block;
      max-width: 100%;
      overflow: visible;
    }

    /* Sort2 outside the table, normal weight */
    .sort2-container {
      width: 100%;
      font-size: 20px;
      text-align: left;
      padding: 5px 0 0 8px;
      font-weight: normal; /* not bold */
    }
  </style>
</head>

<body>
  <div class="right-side">
    <table>
      <tr>
        <td></td>
        <td>[% borrower.phone %]</td>
      </tr>
      <tr>
        <td><span style="font-weight: bold;">[% borrower.cardnumber %]</span></td>
        <td>[% borrower.mobile %]</td>
      </tr>
      <tr>
        <td>[% borrower.categorycode %]</td>
        <td><span id="formatted_date">[% borrower.dateexpiry %]</span></td>
      </tr>

      <!-- Firstname row -->
      <tr class="firstname-row">
        <td>[% borrower.firstname %]</td>
        <td>[% borrower.fax %]</td>
      </tr>
    </table>

    <!-- Sort2 below table -->
    <div class="sort2-container">[% borrower.sort2 %]</div>

    <!-- Barcode -->
    <div class="barcode-container">
      <span class="barcode">*[% borrower.cardnumber %]*</span>
    </div>
  </div>

  <script>
    const dateCell = document.getElementById("formatted_date");
    const rawDate = dateCell.innerText.trim();
    const dateObj = new Date(rawDate);
    if (!isNaN(dateObj)) {
      const day = String(dateObj.getDate()).padStart(2, '0');
      const month = String(dateObj.getMonth() + 1).padStart(2, '0');
      const year = dateObj.getFullYear();
      dateCell.innerText = `${day}/${month}/${year}`;
    }
  </script>
</body>

 

Issue Slip

<h3 style="text-align:center;">Punjab University Library</h3>

<p><strong>Patron ID:</strong> [% borrower.cardnumber %]</p>

<h4>📚 Books Issued Today</h4>
<div id="issuedToday"></div>

<p><strong>Total Book(s) Issued Today:</strong> <span id="issuedCount">0</span></p>

<p><strong>Staff Username:</strong> [% loggedinusername %]</p>

<!-- Hidden raw data -->
<div id="allBooks" style="display:none;">
[% FOREACH checkout IN checkouts %]
  <div class="book"
       data-issuedate="[% checkout.issuedate %]"
       data-barcode="[% checkout.item.barcode %]"
       data-duedate="[% checkout.date_due %]">
  </div>
[% END %]
</div>

<script>
  window.onload = function () {
    const allBooks = document.querySelectorAll("#allBooks .book");
    const issuedTodayContainer = document.getElementById("issuedToday");

    // Today's date in Koha format (YYYY-MM-DD)
    const today = new Date();
    const yyyy = today.getFullYear();
    const mm = String(today.getMonth() + 1).padStart(2, '0');
    const dd = String(today.getDate()).padStart(2, '0');
    const todayStr = `${yyyy}-${mm}-${dd}`;

    let todayCount = 0;

    allBooks.forEach(book => {
      const issuedDate = (book.getAttribute("data-issuedate") || "").trim().split(" ")[0];
      const barcode = book.getAttribute("data-barcode");
      const dueDate = book.getAttribute("data-duedate");

      if (issuedDate === todayStr) {
        todayCount++;
        const entry = document.createElement("div");
        entry.textContent = `${todayCount}) Barcode: ${barcode}, Issued: ${issuedDate}, Due: ${dueDate}`;
        issuedTodayContainer.appendChild(entry);
      }
    });

    document.getElementById("issuedCount").textContent = todayCount;
  };
</script>
 

IntranetUserJS 

 $(document).ready(function () {
  // Only run this code on the returns page
  if (window.location.pathname.includes("/cgi-bin/koha/circ/returns.pl")) {
    let returnedBooks = [];
    let previousRows = 0;

    // Monitor the table of returned books every second
    setInterval(function () {
      let rows = $(".checkedin");
      if (rows.length > previousRows) {
        rows.slice(previousRows).each(function () {
          let barcode = $(this).find(".barcode").text().trim();
          let issued = $(this).find(".issuedate").text().trim();
          if (barcode && issued) {
            returnedBooks.push(`${barcode} – ${issued}`);
          }
        });
        previousRows = rows.length;
      }
    }, 1000);

    // Detect double Enter key press in #barcode field
    let enterCount = 0;
    let enterTimer = null;

    $("#barcode").on("keydown", function (e) {
      if (e.key === "Enter") {
        enterCount++;
        if (enterCount === 2) {
          if (returnedBooks.length > 0) {
            alert("📚 Returned Books:\n\n" + returnedBooks.join("\n"));
            returnedBooks = [];
            previousRows = $(".checkedin").length;
          } else {
            alert("⚠️ No returned books found.");
          }
          clearTimeout(enterTimer);
          enterCount = 0;
        } else {
          enterTimer = setTimeout(function () {
            enterCount = 0;
          }, 2000); // Reset after 2 seconds
        }
      }
    });

    return; // Don't load any other code
  }

  // Your existing circulation (issuance) script
  if (!window.location.pathname.includes("/cgi-bin/koha/circ/circulation.pl")) return;

  $("a[href$='frameworkcode=']").hide();
  $("#Frameworks option[value=Default]").hide();
  $('li.z3950searchFw:first').hide();

  function blockIssuance() {
    $("#checkout_form").hide();
    $(".checkout").hide();
    $("#circ_submit").prop("disabled", true);
  }

  let categoryCodeMatch = $("li:contains('Category')").text().match(/\(([^)]+)\)/);
  if (categoryCodeMatch) {
    let categoryCode = categoryCodeMatch[1];

    if (categoryCode === "W") {
      alert("⚠️ Office Copy Required! Book issuance is blocked until the category is changed.");
      blockIssuance();
    } else if (categoryCode === "V") {
      alert("🚫 Clearance Taken! This patron cannot be issued any books.");
      blockIssuance();
    }

    if (categoryCode === "B" || categoryCode === "C") {
      let blocked = false;
      const today = new Date();

      $("table#issues-table tbody tr").each(function () {
        let dueDateText = $(this).find("td").eq(3).text().trim();
        let dueDateParts = dueDateText.split("/");
        if (dueDateParts.length === 3) {
          let dueDate = new Date(`${dueDateParts[2]}-${dueDateParts[1]}-${dueDateParts[0]}`);
          let diffDays = Math.floor((today - dueDate) / (1000 * 60 * 60 * 24));
          if (diffDays > 30) {
            blocked = true;
            return false;
          }
        }
      });

      if (blocked) {
        alert("⛔ This patron has book(s) overdue by more than 30 days. Further issuance is not allowed.");
        blockIssuance();
      }
    }
  }
});

No comments:

Post a Comment

Total Pageviews