Skip to content

Instantly share code, notes, and snippets.

@thibaultmol
Last active January 2, 2025 13:23
Show Gist options
  • Save thibaultmol/2a8fe7f2e78319f954c64c274beb25f2 to your computer and use it in GitHub Desktop.
Save thibaultmol/2a8fe7f2e78319f954c64c274beb25f2 to your computer and use it in GitHub Desktop.
Breex Snelle invoer chatgpt api
//see other scripts. This is purely here for the name at the top
// ==UserScript==
// @name Billit Invoice AI data extractor
// @version 1.1
// @description Extracts various data from the images in Snelle Invoer by sending it to through openai
// @author Thibaultmol
// @match https://my.breex.be/*
// @match https://my.billit.be/*
// @updateURL https://gist.github.com/thibaultmol/2a8fe7f2e78319f954c64c274beb25f2/raw/071d4e05e06ae002e7ed76a1bf2d0ed8735fdd6f/billit_data-extractor.user.js
// @downloadURL https://gist.github.com/thibaultmol/2a8fe7f2e78319f954c64c274beb25f2/raw/071d4e05e06ae002e7ed76a1bf2d0ed8735fdd6f/billit_data-extractor.user.js
// @grant none
// ==/UserScript==
(function() {
'use strict';
// European country codes for IBAN
const EUROPEAN_COUNTRY_CODES = [
'AD', 'AT', 'BE', 'BG', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE',
'ES', 'FI', 'FR', 'GB', 'GI', 'GR', 'HR', 'HU', 'IE', 'IS',
'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'NL', 'NO', 'PL',
'PT', 'RO', 'SE', 'SI', 'SK', 'SM', 'VA'
];
// Function to get current domain
function getCurrentDomain() {
return window.location.hostname;
}
// Function to convert IBAN with spaces to format needed for URL
function formatIBANForUrl(iban) {
return iban.replace(/\s+/g, '');
}
// Function to check if string matches IBAN pattern
function isIBAN(text) {
const cleanText = text.trim().replace(/\s+/g, '');
// Check if starts with any valid country code followed by 2 digits
const countryCodePattern = EUROPEAN_COUNTRY_CODES.join('|');
const ibanRegex = new RegExp(`^(${countryCodePattern})\\d{2}[\\dA-Z]+$`);
return ibanRegex.test(cleanText);
}
// Function to convert span to link
function convertSpanToLink() {
const spans = document.querySelectorAll('span.form-control-plaintext');
const currentDomain = getCurrentDomain();
spans.forEach(span => {
const text = span.textContent.trim();
if (isIBAN(text)) {
const formattedIBAN = formatIBANForUrl(text);
const link = document.createElement('a');
link.href = `https://${currentDomain}/Payment/Index?Search=${formattedIBAN}`;
link.textContent = text;
link.className = 'form-control-plaintext';
link.style.textDecoration = 'underline';
span.parentNode.replaceChild(link, span);
}
});
}
// Initial conversion
convertSpanToLink();
// Monitor for dynamic content changes
const observer = new MutationObserver((mutations) => {
convertSpanToLink();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
})();
// ==UserScript==
// @name Billit Missing Order Numbers Checker
// @version 1.2
// @description Adds a button to check for missing order numbers on the Incoming invoices page
// @author Thibaultmol
// @match https://my.breex.be/Order/Income/Invoice/*
// @match https://my.billit.be/Order/Income/Invoice/*
// @updateURL https://gist.github.com/thibaultmol/2a8fe7f2e78319f954c64c274beb25f2/raw/071d4e05e06ae002e7ed76a1bf2d0ed8735fdd6f/billit_find-missing-invoices.user.js
// @downloadURL https://gist.github.com/thibaultmol/2a8fe7f2e78319f954c64c274beb25f2/raw/071d4e05e06ae002e7ed76a1bf2d0ed8735fdd6f/billit_find-missing-invoices.user.js
// @grant none
// ==/UserScript==
(function() {
'use strict';
function findMissingNumbers(numbers) {
numbers = numbers.map(n => parseInt(n)).sort((a, b) => a - b);
let missing = [];
for(let i = 0; i < numbers.length - 1; i++) {
let diff = numbers[i + 1] - numbers[i];
if(diff > 1) {
for(let j = 1; j < diff; j++) {
missing.push(numbers[i] + j);
}
}
}
return missing.sort((a, b) => b - a);
}
function checkMissingNumbers() {
let orderNumbers = [];
document.querySelectorAll('td[sortcolumn="OrderNumber"]').forEach(td => {
orderNumbers.push(td.textContent.trim());
});
let missingNumbers = findMissingNumbers(orderNumbers);
if(missingNumbers.length > 0) {
alert('Missing order numbers:\n' + missingNumbers.join(', '));
} else {
alert('No missing order numbers found!');
}
}
function addButton() {
// Remove existing button if present
const existingButton = document.querySelector('.check-missing-btn');
if (existingButton) {
existingButton.remove();
}
const buttonRow = document.querySelector('.buttonRow');
if(buttonRow) {
const newButton = document.createElement('button');
newButton.className = 'btn-sm btn-secondary btn hideOnPost check-missing-btn';
newButton.type = 'button';
newButton.innerHTML = '<i class="fas fa-search"></i><span class="ml-2">Check Missing</span>';
newButton.addEventListener('click', checkMissingNumbers);
newButton.style.setProperty('--bs-btn-focus-box-shadow', '0 0 0 0.2rem rgba(41, 255, 114, 0.5)');
newButton.style.setProperty('box-shadow', '0px 0px 0px 4px inset rgba(41, 255, 114, 0.5)', 'important');
const btnGroup = buttonRow.querySelector('.btn-group');
buttonRow.insertBefore(newButton, btnGroup);
}
}
// Initial button add
addButton();
// Watch for AJAX content updates
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.target.id === 'OrderList' &&
mutation.type === 'childList' &&
mutation.addedNodes.length > 0) {
// Wait a brief moment for the DOM to settle
setTimeout(addButton, 100);
break;
}
}
});
// Start observing the document with the configured parameters
observer.observe(document.body, {
childList: true,
subtree: true
});
// Also watch for URL changes via History API
const originalPushState = history.pushState;
history.pushState = function() {
setTimeout(addButton, 100);
return originalPushState.apply(this, arguments);
};
const originalReplaceState = history.replaceState;
history.replaceState = function() {
setTimeout(addButton, 100);
return originalReplaceState.apply(this, arguments);
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment