Если и вас как и у меня возникла проблема с тем что у части назначений МСЗ не выставлена дата окончания и вам теперь нужно выставлять их в ручную, а записей этих миллион, не беда. Делюсь с вами накиданным на скорую руку скриптом для автоматизации этого процесса:
Скрипт автоматически выставляет всем найденным фактам назначения (у которых отсутствует дата окончания) эту дату в конец соответствующего месяца и создаёт необходимый Файл На Подписание. Также имеется кнопка для скачивания сразу всех созданных файлов и для загрузки их всех после подписания.
Для работы скрипта нужно войти как обычно в ЕГИССО, нажать F12 чтобы открыть консоль, вставить в неё скрипт и нажать Enter. После этого на сайте должны появиться дополнительные кнопки как на скриншоте. Далее копируем столбец со СНИЛСами из экселя, вставляем их в соответствующее поле и жмём Обработать СНИЛСы, в консоли начнут появляться сообщения (рекомендую также выбрать для удобства монитор сетевой активности и следить за запросами в нём), далее когда СНИЛСы обработаются в разделе Файлы На Подписание появятся файлы. Их тоже можно скачать все сразу по кнопке Скачать Файлы На Подписание (нужно разрешить браузеру загрузку нескольких файлов).
Подписываем файлы как обычно (я использую для этого Такском КриптоЛайн), все подписанные файлы можно загрузить сразу пачкой, сначала выбрав их с помощью кнопки Выбрать Файлы, а потом нажав Загрузить xml,p7s Файлы.
За раз можно обработать не больше 250 СНИЛСов (рекомендую не больше 200), скрипт делался для себя на скорую руку и не всегда хорошо работает, как собственно и весь сайт ЕГИССО , выкладываю в надежде что кому-нибудь пригодится.
//последний день месяца function getLastDayOfMonth(date) { // Create a new date object based on the input date const inputDate = new Date(date); // Set the date to the first day of the next month const nextMonth = new Date(inputDate.getFullYear(), inputDate.getMonth() + 1, 1); // Subtract one day to get the last day of the current month const lastDay = new Date(nextMonth - 1); // Format the date as YYYY-MM-DD const formattedDate = lastDay.toISOString().split('T')[0]; return formattedDate; // Return the formatted last day of the month } //получить данный по выплатам async function get_data(snils) { const today = new Date(); const formattedDate = today.toISOString().split('T')[0]; // Format date as YYYY-MM-DD const response = await fetch("https://pd.egisso.ru/portal/api/rest/v3/assignment/journal?offset=0&limit=250", { headers: { "accept": "application/json, text/plain, */*", "content-type": "application/json", }, referrer: "https://pd.egisso.ru/portal/provider/client/", body: JSON.stringify({ dateDecisionBegin: "2018-01-01", dateDecisionEnd: formattedDate, // Use today's date beginDate: "2018-01-01", endDate: formattedDate, // Use today's date snils: snils, // Use the provided snils sort: [{ field: "decisionDateId", direction: "DESC" }] }), method: "POST", mode: "cors", credentials: "include" }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status} ${snils}`); //return `HTTP error! status: ${response.status} ${snils}` } const data = await response.json(); // Parse the JSON response return data; // Return the JSON data } //задать новую дату окончания если её нет async function modify_assignment(data) { // Check if endDate is empty if (!data.endDate) { const url = `https://pd.egisso.ru/portal/api/rest/assignment/modification/04/${data.packageId}/${data.uuid}?quantity=${data.quantity}&endDate=${getLastDayOfMonth(data.beginDate)}`; const response = await fetch(url, { headers: { "accept": "application/json, text/plain, */*", }, referrer: "https://pd.egisso.ru/portal/provider/client/", body: null, method: "POST", mode: "cors", credentials: "include" }); if (!response.ok) { //throw new Error(`HTTP error! status: ${response.status}`); return `HTTP error! status: ${response.status} ${data.uuid}?quantity=${data.quantity}&endDate=${getLastDayOfMonth(data.beginDate)} ` } const result = await response; // Parse the JSON response return result; // Return the JSON data } else { return { message: "endDate is not empty, no fetch performed." }; } } //экспортировать изменения в xml файл по массиву айдишников function exportAssignmentsByIds(ids) { // Directly use the provided ids parameter in the request body const requestBody = ids; if (JSON.parse(ids).ids.length === 0){ return "##### no ids ######" } return fetch("https://pd.egisso.ru/portal/api/rest/v2/package/export/assignment/byid/xml", { headers: { "accept": "application/json, text/plain, */*", "content-type": "application/json" }, referrer: "https://pd.egisso.ru/portal/provider/client/", body: requestBody, // Use the formatted request body method: "POST", mode: "cors", credentials: "include" }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return "############################# file created ####################################";//response.json(); // Assuming the response is JSON }) .then(data => { console.log(data); // Handle the response data }) .catch(error => { console.error('Error:', error); // Handle any errors }); } // вынуть изменения async function fetchAssignmentChanges(snils) { const requestBody = { showAll: true, statuses: ["PREPARED", "ERROR"], sort: [{ field: "decisionDate", direction: "DESC" }], snils: snils // Replace with the function parameter }; return fetch("https://pd.egisso.ru/portal/api/rest/v3/assignment/changes?offset=0&limit=250", { headers: { "accept": "application/json, text/plain, */*", "content-type": "application/json" }, referrer: "https://pd.egisso.ru/portal/provider/client/", body: JSON.stringify(requestBody), // Convert the object to a JSON string method: "POST", mode: "cors", credentials: "include" }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response; }) .then(async data => { res = await data.json() console.log(res) // Extract IDs from the response array const ids = res.filter(item => { if (item.lmsz == null){ console.log("####::: lmsz errror :::####");} return item.lmsz !== null }).map(item => item.id); return JSON.stringify({ ids: ids }); // Return the IDs in the specified format }) .catch(error => { console.error('Error:', error); // Handle any errors return null; // Return null or handle the error as needed }); } //сделать файл с изменениями по снилсу async function prepair_a_file(snils){ data = await get_data(snils) for (entety in data){ console.log(await modify_assignment (data[entety])) } await wait(3000); changes = await fetchAssignmentChanges(snils) export_message = exportAssignmentsByIds(changes); if (export_message !== "##### no ids ######"){ return true; } else { return false; } } //######################################################################## //download files //######################################################################## // Загрузить список файлов async function fetchFiles() { try { const response = await fetch("https://pd.egisso.ru/portal/api/rest/package/files?offset=0&limit=250", { headers: { "accept": "application/json, text/plain, */*", "content-type": "application/json", }, referrer: "https://pd.egisso.ru/portal/provider/client/", body: JSON.stringify({ packageType: "ASSIGNMENT", sort: [] }), // Use JSON.stringify for the body method: "POST", credentials: "include" }); if (!response.ok) { throw new Error('Network response was not ok'); } const data = await response.json(); // Parse the JSON response return data; // Return the array from the response } catch (error) { console.error('There was a problem with the fetch operation:', error); return null; // Return null or handle the error as needed } } // загрузить файлы ( не хочет загружать больше 10 за раз) function downloadFiles(entries) { entries.forEach(entry => { if (entry.lastState === "CREATED") { const url = `https://pd.egisso.ru/portal/api/rest/v2/package/download/${entry.id}`; fetch(url, { headers: { "accept": "application/json, text/plain, */*", }, referrer: "https://pd.egisso.ru/portal/provider/client/", method: "GET", credentials: "include" }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.blob(); // Convert the response to a Blob }) .then(blob => { const fileName = entry.fileName; // Use the fileName from the entry const downloadUrl = window.URL.createObjectURL(blob); // Create a URL for the Blob const a = document.createElement('a'); // Create an anchor element a.style.display = 'none'; // Hide the anchor a.href = downloadUrl; // Set the href to the Blob URL a.download = fileName; // Set the desired file name document.body.appendChild(a); // Append the anchor to the body a.click(); // Programmatically click the anchor to trigger the download document.body.removeChild(a); // Remove the anchor from the document window.URL.revokeObjectURL(downloadUrl); // Clean up the URL object }) .catch(error => { console.error('There was a problem with the fetch operation:', error); }); } }); } //порезать список файлов по 10 штук function splitArrayIntoChunks(array, chunkSize) { const chunks = []; for (let i = 0; i < array.length; i += chunkSize) { chunks.push(array.slice(i, i + chunkSize)); } return chunks; } //######################################################################################### // create and download buttons //######################################################################################### const textarea = document.createElement("textarea"); textarea.id = "dynamicTextarea"; textarea.placeholder = "Enter your input here"; textarea.rows = 5; // Number of visible rows textarea.style.width = "300px"; // Set width textarea.style.overflowY = "auto"; // Enable vertical scroll textarea.style.textAlign = "right"; // Align text to the right // Create a button const button1 = document.createElement("button"); button1.innerText = "Обработать СНИЛСы"; button1.onclick = function() { const inputValue = textarea.value; processBunch(inputValue); }; // Append the textarea and button to the body document.body.appendChild(textarea); document.body.appendChild(button1); const button2 = document.createElement("button"); button2.innerText = "Скачать файлы на подписание"; button2.onclick = download_files document.body.appendChild(button2); //########################################################################################## // file upload //########################################################################################## // Create the file input element const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.id = 'fileInput'; fileInput.multiple = true; // Allow multiple file selection // Create the upload button element const uploadButton = document.createElement('button'); uploadButton.id = 'uploadButton'; uploadButton.textContent = '...........Загрузить xml,p7s файлы'; // Append the elements to the body (or any other container) document.body.appendChild(fileInput); document.body.appendChild(uploadButton); // Function to group files into pairs function groupFiles(files) { const fileMap = new Map(); // Group files by their base name (without extension) for (const file of files) { const baseName = file.name.replace(/(\.xml|\.xml\.p7s)$/, ''); // Remove the extension if (!fileMap.has(baseName)) { fileMap.set(baseName, []); } fileMap.get(baseName).push(file); } // Filter out pairs (only keep those with both .xml and .xml.p7s) const pairs = []; for (const [baseName, groupedFiles] of fileMap) { if (groupedFiles.length === 2) { pairs.push(groupedFiles); // Add the pair to the result } } return pairs; } // Add event listener for the upload button uploadButton.addEventListener('click', async () => { const files = fileInput.files; // Get the selected files if (files.length === 0) { console.log('No files selected.'); return; } const filePairs = groupFiles(files); // Group files into pairs if (filePairs.length === 0) { console.log('No valid pairs found for upload.'); return; } // Upload each pair for (const pair of filePairs) { const formData = new FormData(); // Sort the pair to ensure .xml goes first and .xml.p7s goes second const xmlFile = pair.find(file => file.name.endsWith('.xml')); const p7sFile = pair.find(file => file.name.endsWith('.xml.p7s')); if (xmlFile) formData.append('files', xmlFile); // Append the .xml file first if (p7sFile) formData.append('files', p7sFile); // Append the .xml.p7s file second try { const response = await fetch("https://pd.egisso.ru/portal/api/rest/v2/package/upload", { method: "POST", body: formData, credentials: "include" }); if (!response.ok) { throw new Error('Network response was not ok'); } const data = await response.json(); // Handle the response as needed console.log(data); // Process the response data } catch (error) { console.error('There was a problem with the fetch operation:', error); } } }); //записи из таблицы в массив function convertStringToArray(inputString) { return inputString.split('\n') .map(item => item.trim()) .filter(item => item !== "") .map(item => item.padStart(11, '0')); // Add leading zeros if shorter than 11 digits } //задержка function wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function download_files() { files = await fetchFiles() files_in_chuncks = splitArrayIntoChunks(files, 10) for (i in files_in_chuncks){ await wait(3000); downloadFiles(files_in_chuncks[i]) } console.log("### files downloaded ###") } async function processBunch(exel_str){ bunch = convertStringToArray(exel_str); var counter = 0 for (snils_n in bunch) { console.log(`################# №${snils_n} snils: ${bunch[snils_n]} ################`); if ( await prepair_a_file(bunch[snils_n]) ){ counter+=1 } } console.log(`###### files created ${counter} ######`) }