test commit
This commit is contained in:
parent
eff297ad81
commit
6a4a65f24f
|
|
@ -19,6 +19,15 @@ fixtures = [
|
|||
}
|
||||
]
|
||||
|
||||
doctype_js = {
|
||||
"XML Mapping Tool": [
|
||||
"public/js/xml_mapping/xml_parser.js",
|
||||
"public/js/xml_mapping/field_generator.js",
|
||||
"public/js/xml_mapping/doctype_field_selector.js",
|
||||
"public/js/xml_mapping/mapping_storage.js",
|
||||
"public/js/xml_mapping/xml_generator.js"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
# Includes in <head>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
// taxes_az/public/js/xml_mapping/doctype_field_selector.js
|
||||
|
||||
frappe.provide("taxes_az.xml_mapping");
|
||||
|
||||
taxes_az.xml_mapping.DoctypeFieldSelector = class DoctypeFieldSelector {
|
||||
constructor(frm) {
|
||||
this.frm = frm;
|
||||
}
|
||||
|
||||
// Получить список полей DocType
|
||||
async getFieldsForDoctype(doctype) {
|
||||
return new Promise((resolve, reject) => {
|
||||
frappe.model.with_doctype(doctype, () => {
|
||||
try {
|
||||
const meta = frappe.get_meta(doctype);
|
||||
if (!meta) {
|
||||
throw new Error(`DocType ${doctype} not found`);
|
||||
}
|
||||
|
||||
const fields = meta.fields.filter(field => {
|
||||
// Исключаем служебные поля и разделы
|
||||
return !['Section Break', 'Column Break', 'Tab Break', 'HTML', 'Button'].includes(field.fieldtype);
|
||||
});
|
||||
|
||||
resolve(fields);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Добавить селекторы полей для каждого XML-пути
|
||||
async attachFieldSelectors(container, xmlPaths) {
|
||||
if (!this.frm.doc.target_doctype) {
|
||||
frappe.throw(__('Please select a target DocType first'));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const fields = await this.getFieldsForDoctype(this.frm.doc.target_doctype);
|
||||
|
||||
// Добавляем селектор для каждого XML-пути
|
||||
container.find('.xml-field-row').each((i, row) => {
|
||||
const $row = $(row);
|
||||
const xmlPath = $row.data('path');
|
||||
const $selector = $row.find('.xml-field-selector');
|
||||
|
||||
// Создаем выпадающий список
|
||||
const select = document.createElement('select');
|
||||
select.classList.add('form-control', 'xml-field-map-select');
|
||||
select.dataset.xmlPath = xmlPath;
|
||||
|
||||
// Опция "Не сопоставлять"
|
||||
const defaultOption = document.createElement('option');
|
||||
defaultOption.value = "";
|
||||
defaultOption.textContent = __("-- Not mapped --");
|
||||
select.appendChild(defaultOption);
|
||||
|
||||
// Добавляем опции для каждого поля DocType
|
||||
fields.forEach(field => {
|
||||
const option = document.createElement('option');
|
||||
option.value = field.fieldname;
|
||||
option.textContent = `${field.label || field.fieldname} (${field.fieldname})`;
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
||||
// Добавляем селектор в контейнер
|
||||
$selector.empty().append(select);
|
||||
|
||||
// Устанавливаем выбранное значение из сохраненных данных
|
||||
if (this.frm.doc.mapping_data) {
|
||||
try {
|
||||
const mappingData = JSON.parse(this.frm.doc.mapping_data);
|
||||
if (mappingData[xmlPath]) {
|
||||
select.value = mappingData[xmlPath];
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error parsing mapping data:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Обработчик изменения
|
||||
$(select).on('change', () => {
|
||||
this._saveMappingData();
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
frappe.throw(`Error loading DocType fields: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
_saveMappingData() {
|
||||
const mappingData = {};
|
||||
|
||||
$('.xml-field-map-select').each((i, select) => {
|
||||
const $select = $(select);
|
||||
const xmlPath = $select.data('xml-path');
|
||||
const fieldname = $select.val();
|
||||
|
||||
if (fieldname) {
|
||||
mappingData[xmlPath] = fieldname;
|
||||
}
|
||||
});
|
||||
|
||||
// Просто устанавливаем значение, но не сохраняем автоматически
|
||||
this.frm.set_value('mapping_data', JSON.stringify(mappingData));
|
||||
|
||||
// Уведомление об обновлении маппинга
|
||||
frappe.show_alert({
|
||||
message: __('Mapping updated. Remember to save the document.'),
|
||||
indicator: 'blue'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
// taxes_az/public/js/xml_mapping/field_generator.js
|
||||
|
||||
frappe.provide("taxes_az.xml_mapping");
|
||||
|
||||
taxes_az.xml_mapping.FieldGenerator = class FieldGenerator {
|
||||
constructor(frm) {
|
||||
this.frm = frm;
|
||||
this.fieldContainer = $('<div class="xml-fields-container"></div>');
|
||||
}
|
||||
|
||||
// Очистить все динамически созданные поля
|
||||
clearFields() {
|
||||
this.fieldContainer.empty();
|
||||
if (this.section) {
|
||||
this.section.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Создать UI для выбора полей
|
||||
createFieldsUI(xmlStructure) {
|
||||
// Проверяем, существует ли уже секция
|
||||
if ($('.xml-mapping-section').length) {
|
||||
this.clearFields();
|
||||
} else {
|
||||
this.clearFields();
|
||||
|
||||
// Создаем секцию для полей XML
|
||||
this.section = $('<div class="xml-mapping-section frappe-card"></div>');
|
||||
const sectionTitle = $('<h5 class="frappe-card-header p-3">' + __('XML Fields Mapping') + '</h5>');
|
||||
this.section.append(sectionTitle);
|
||||
|
||||
// Добавляем поле поиска
|
||||
const searchField = $(`
|
||||
<div class="form-group p-3">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control xml-search-field" placeholder="${__('Search in XML fields...')}">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-default xml-search-button">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
this.section.append(searchField);
|
||||
this.section.append(this.fieldContainer);
|
||||
|
||||
// Добавляем секцию в форму после основной области формы
|
||||
$('.form-layout').after(this.section);
|
||||
|
||||
// Добавляем обработчик поиска
|
||||
searchField.find('.xml-search-field, .xml-search-button').on('keyup click', () => {
|
||||
const searchText = searchField.find('.xml-search-field').val().toLowerCase();
|
||||
|
||||
this.fieldContainer.find('.xml-field-row').each((i, row) => {
|
||||
const $row = $(row);
|
||||
const path = $row.find('.xml-field-path').text().toLowerCase();
|
||||
const value = $row.find('.xml-field-value').text().toLowerCase();
|
||||
|
||||
if (path.includes(searchText) || value.includes(searchText)) {
|
||||
$row.show();
|
||||
} else {
|
||||
$row.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Для каждого пути создаем элемент интерфейса
|
||||
xmlStructure.fieldPaths.forEach(fieldInfo => {
|
||||
this._createFieldElement(fieldInfo);
|
||||
});
|
||||
|
||||
// Инициализируем селектор DocType полей
|
||||
if (this.frm.doc.target_doctype) {
|
||||
const fieldSelector = new taxes_az.xml_mapping.DoctypeFieldSelector(this.frm);
|
||||
fieldSelector.attachFieldSelectors(this.fieldContainer, xmlStructure.fieldPaths);
|
||||
}
|
||||
|
||||
// Добавляем стили для полей
|
||||
this._addStyles();
|
||||
}
|
||||
|
||||
clearFields() {
|
||||
this.fieldContainer = $('<div class="xml-fields-container p-3"></div>');
|
||||
|
||||
// Если секция существует, очищаем только контейнер полей
|
||||
if ($('.xml-mapping-section').length) {
|
||||
$('.xml-fields-container').replaceWith(this.fieldContainer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
clearFields() {
|
||||
this.fieldContainer = $('<div class="xml-fields-container p-3"></div>');
|
||||
if (this.section) {
|
||||
this.section.remove();
|
||||
}
|
||||
}
|
||||
|
||||
clearFields() {
|
||||
this.fieldContainer = $('<div class="xml-fields-container"></div>');
|
||||
if (this.section) {
|
||||
this.section.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Создание отдельного элемента поля
|
||||
_createFieldElement(fieldInfo) {
|
||||
const fieldRow = $(`
|
||||
<div class="xml-field-row" data-path="${fieldInfo.path}">
|
||||
<div class="xml-field-path">${fieldInfo.path}</div>
|
||||
<div class="xml-field-value">${fieldInfo.value}</div>
|
||||
<div class="xml-field-selector"></div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
this.fieldContainer.append(fieldRow);
|
||||
}
|
||||
|
||||
// Добавление стилей для UI полей
|
||||
_addStyles() {
|
||||
if (!$('#xml_mapping_styles').length) {
|
||||
$('head').append(`
|
||||
<style id="xml_mapping_styles">
|
||||
.xml-fields-container {
|
||||
margin-top: 15px;
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
}
|
||||
.xml-field-row {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
padding: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.xml-field-path {
|
||||
flex: 1.5;
|
||||
font-weight: bold;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-all;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.xml-field-value {
|
||||
flex: 1;
|
||||
color: #555;
|
||||
margin: 0 10px;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
.xml-field-selector {
|
||||
flex: 1.5;
|
||||
}
|
||||
.xml-search-field {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// taxes_az/public/js/xml_mapping/xml_generator.js
|
||||
|
||||
frappe.provide("taxes_az.xml_mapping");
|
||||
|
||||
taxes_az.xml_mapping.XMLGenerator = class XMLGenerator {
|
||||
constructor(frm) {
|
||||
this.frm = frm;
|
||||
}
|
||||
|
||||
// Генерация XML на основе данных DocType и правил маппинга
|
||||
async generateXML(doctypeName, docname) {
|
||||
try {
|
||||
// Загружаем данные DocType
|
||||
const docData = await this._loadDocTypeData(doctypeName, docname);
|
||||
|
||||
// Загружаем правила маппинга
|
||||
const mappingRules = JSON.parse(this.frm.doc.mapping_data || '{}');
|
||||
|
||||
// Загружаем шаблон XML
|
||||
const xmlTemplate = this.frm.doc.xml_sample_file;
|
||||
|
||||
// Создаем DOM из шаблона XML
|
||||
const parser = new DOMParser();
|
||||
const xmlDoc = parser.parseFromString(xmlTemplate, "text/xml");
|
||||
|
||||
// Применяем правила маппинга
|
||||
for (const xmlPath in mappingRules) {
|
||||
const doctypeField = mappingRules[xmlPath];
|
||||
const value = docData[doctypeField];
|
||||
|
||||
if (value !== undefined) {
|
||||
this._setXMLValueByPath(xmlDoc, xmlPath, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Преобразуем DOM обратно в строку XML
|
||||
const serializer = new XMLSerializer();
|
||||
const xmlString = serializer.serializeToString(xmlDoc);
|
||||
|
||||
return xmlString;
|
||||
} catch (error) {
|
||||
frappe.throw(`Error generating XML: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Загрузка данных DocType
|
||||
async _loadDocTypeData(doctypeName, docname) {
|
||||
return new Promise((resolve, reject) => {
|
||||
frappe.call({
|
||||
method: 'frappe.client.get',
|
||||
args: {
|
||||
doctype: doctypeName,
|
||||
name: docname
|
||||
},
|
||||
callback: (response) => {
|
||||
if (response.message) {
|
||||
resolve(response.message);
|
||||
} else {
|
||||
reject(new Error('Failed to load document data'));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Установка значения в XML по пути
|
||||
_setXMLValueByPath(xmlDoc, path, value) {
|
||||
try {
|
||||
// Проверяем, является ли путь атрибутом
|
||||
if (path.includes('@')) {
|
||||
const [elementPath, attrName] = path.split('@');
|
||||
const elementPathParts = elementPath.split('/').filter(p => p);
|
||||
|
||||
// Получаем элемент
|
||||
let element = xmlDoc.documentElement;
|
||||
for (const part of elementPathParts) {
|
||||
if (part !== element.nodeName) {
|
||||
const elements = element.getElementsByTagName(part);
|
||||
if (elements.length === 0) {
|
||||
throw new Error(`Element ${part} not found in path ${path}`);
|
||||
}
|
||||
element = elements[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Устанавливаем атрибут
|
||||
element.setAttribute(attrName, value);
|
||||
} else {
|
||||
// Путь к элементу
|
||||
const pathParts = path.split('/').filter(p => p);
|
||||
|
||||
// Получаем элемент
|
||||
let element = xmlDoc.documentElement;
|
||||
for (let i = 0; i < pathParts.length; i++) {
|
||||
const part = pathParts[i];
|
||||
|
||||
if (i === pathParts.length - 1) {
|
||||
// Последний элемент в пути - целевой элемент
|
||||
const elements = element.getElementsByTagName(part);
|
||||
if (elements.length) {
|
||||
elements[0].textContent = value;
|
||||
}
|
||||
} else if (part !== element.nodeName) {
|
||||
const elements = element.getElementsByTagName(part);
|
||||
if (elements.length === 0) {
|
||||
throw new Error(`Element ${part} not found in path ${path}`);
|
||||
}
|
||||
element = elements[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error setting value for path ${path}:`, error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// taxes_az/public/js/xml_mapping/xml_parser.js
|
||||
|
||||
frappe.provide("taxes_az.xml_mapping");
|
||||
|
||||
taxes_az.xml_mapping.XMLParser = class XMLParser {
|
||||
constructor() {
|
||||
this.fieldPaths = [];
|
||||
}
|
||||
|
||||
// Основная функция парсинга XML
|
||||
parseXML(xmlString) {
|
||||
const parser = new DOMParser();
|
||||
try {
|
||||
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
||||
|
||||
// Проверка наличия ошибок парсинга
|
||||
const parseError = xmlDoc.getElementsByTagName("parsererror");
|
||||
if (parseError.length > 0) {
|
||||
frappe.throw(__("Invalid XML: ") + parseError[0].textContent);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Получить корневой элемент
|
||||
const rootElement = xmlDoc.documentElement;
|
||||
this.fieldPaths = [];
|
||||
|
||||
// Рекурсивно извлечь пути к полям
|
||||
this._extractFieldPaths(rootElement, "");
|
||||
|
||||
return {
|
||||
rootElement: rootElement.nodeName,
|
||||
fieldPaths: this.fieldPaths
|
||||
};
|
||||
} catch (error) {
|
||||
frappe.throw(__("Error parsing XML: ") + error.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Рекурсивное извлечение путей к полям
|
||||
_extractFieldPaths(element, currentPath) {
|
||||
const nodeName = element.nodeName;
|
||||
const newPath = currentPath ? `${currentPath}/${nodeName}` : nodeName;
|
||||
|
||||
// Если у элемента есть текстовое содержимое и нет дочерних элементов,
|
||||
// считаем его полем
|
||||
if (element.childNodes.length === 1 && element.childNodes[0].nodeType === 3) {
|
||||
this.fieldPaths.push({
|
||||
path: newPath,
|
||||
value: element.textContent.trim(),
|
||||
type: 'field'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Если у элемента есть атрибуты, извлекаем их как поля
|
||||
if (element.attributes && element.attributes.length > 0) {
|
||||
for (let i = 0; i < element.attributes.length; i++) {
|
||||
const attr = element.attributes[i];
|
||||
this.fieldPaths.push({
|
||||
path: `${newPath}/@${attr.name}`,
|
||||
value: attr.value,
|
||||
type: 'attribute'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Рекурсивно обрабатываем дочерние элементы
|
||||
const childElements = element.childNodes;
|
||||
for (let i = 0; i < childElements.length; i++) {
|
||||
const child = childElements[i];
|
||||
if (child.nodeType === 1) { // ELEMENT_NODE
|
||||
this._extractFieldPaths(child, newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Building construction and simplified tax declaration", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Building construction and simplified tax declaration', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Building construction and simplified tax declaration', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Building construction and simplified tax declaration', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Certificate on non-emergence of tax liability", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Certificate on non-emergence of tax liability', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Certificate on non-emergence of tax liability', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Certificate on non-emergence of tax liability', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Declaration of mining tax", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Declaration of mining tax', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Declaration of mining tax', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Declaration of mining tax', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
"topdansat\u0131\u015f_qiym\u0259ti_il\u0259_tab",
|
||||
"html_hken",
|
||||
"section_break_oytj",
|
||||
"table_rhfx",
|
||||
"topdansat\u0131\u015f_qiym\u0259ti_il\u0259",
|
||||
"723b\u00fcdc\u0259y\u0259\u00f6d\u0259nilm\u0259livergininm\u0259bl\u0259\u011fi",
|
||||
"faydal\u0131_qaz\u0131nt\u0131lar\u0131n_hasilat\u0131n_miqdar\u0131_il\u0259_tab",
|
||||
"html_ybie",
|
||||
|
|
@ -236,11 +236,6 @@
|
|||
"fieldname": "section_break_oytj",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "table_rhfx",
|
||||
"fieldtype": "Table",
|
||||
"options": "Declaration of mining tax Topdansatis qiymeti"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_rpno",
|
||||
"fieldtype": "Section Break"
|
||||
|
|
@ -283,11 +278,16 @@
|
|||
"fieldname": "717hesablanm\u0131\u015fvergim\u0259bl\u0259\u011fininc\u0259mi",
|
||||
"fieldtype": "Int",
|
||||
"label": "717. Hesablanm\u0131\u015f vergi m\u0259bl\u0259\u011finin c\u0259mi"
|
||||
},
|
||||
{
|
||||
"fieldname": "topdansat\u0131\u015f_qiym\u0259ti_il\u0259",
|
||||
"fieldtype": "Table",
|
||||
"options": "Declaration of mining tax Topdansatis qiymeti"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-01-12 17:23:11.436483",
|
||||
"modified": "2025-04-22 22:09:55.802593",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Declaration of mining tax",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Declaration of simplified tax", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Declaration of simplified tax', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Declaration of simplified tax', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Declaration of simplified tax', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Declaration of simplified tax on cash withdrawals", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Declaration of simplified tax on cash withdrawals', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Declaration of simplified tax on cash withdrawals', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Declaration of simplified tax on cash withdrawals', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Declaration of value added tax", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Declaration of value added tax', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Declaration of value added tax', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Declaration of value added tax', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Declaration of withholding tax on winnings", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Declaration of withholding tax on winnings', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Declaration of withholding tax on winnings', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Declaration of withholding tax on winnings', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2024, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Excise declaration", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Excise declaration', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Excise declaration', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Excise declaration', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2024, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Export declaration", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Export declaration', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Export declaration', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Export declaration', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Housing construction simplified tax declaration", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Housing construction simplified tax declaration', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Housing construction simplified tax declaration', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Housing construction simplified tax declaration', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Income tax return", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Income tax return', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Income tax return', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Income tax return', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Income tax return of a private notary", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Income tax return of a private notary', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Income tax return of a private notary', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Income tax return of a private notary', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Land tax declaration", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Land tax declaration', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Land tax declaration', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Land tax declaration', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Profit tax with special tax regime", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Profit tax with special tax regime', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Profit tax with special tax regime', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Profit tax with special tax regime', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Property tax return", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Property tax return', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Property tax return', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Property tax return', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Quarterly report on unemployment insurance", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Quarterly report on unemployment insurance', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Quarterly report on unemployment insurance', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Quarterly report on unemployment insurance', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Real estate simplified tax declaration", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Real estate simplified tax declaration', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Real estate simplified tax declaration', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Real estate simplified tax declaration', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("REFERENCE on controlled transactions", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('REFERENCE on controlled transactions', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'REFERENCE on controlled transactions', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'REFERENCE on controlled transactions', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Report on collection of state duty", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Report on collection of state duty', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Report on collection of state duty', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Report on collection of state duty', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Road tax 2", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Road tax 2', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Road tax 2', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Road tax 2', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Single declaration related to salaried and non-salaried work", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Single declaration related to salaried and non-salaried work', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Single declaration related to salaried and non-salaried work', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Single declaration related to salaried and non-salaried work', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Tax return withheld at source of payment", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Tax return withheld at source of payment', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Tax return withheld at source of payment', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Tax return withheld at source of payment', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("VAT calculated on the amount paid to a non-resident", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('VAT calculated on the amount paid to a non-resident', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'VAT calculated on the amount paid to a non-resident', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'VAT calculated on the amount paid to a non-resident', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,33 @@
|
|||
// Copyright (c) 2025, Jey Soft and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Withholding tax return of foreign subcontractors", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Withholding tax return of foreign subcontractors', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Withholding tax return of foreign subcontractors', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Withholding tax return of foreign subcontractors', // Замените на имя DocType
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML file generated and downloaded'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# Copyright (c) 2025, Jey Soft and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.tests import IntegrationTestCase, UnitTestCase
|
||||
|
||||
|
||||
# On IntegrationTestCase, the doctype test records and all
|
||||
# link-field test record depdendencies are recursively loaded
|
||||
# Use these module variables to add/remove to/from that list
|
||||
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||
|
||||
|
||||
class UnitTestXMLMappingTool(UnitTestCase):
|
||||
"""
|
||||
Unit tests for XMLMappingTool.
|
||||
Use this class for testing individual functions and methods.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class IntegrationTestXMLMappingTool(IntegrationTestCase):
|
||||
"""
|
||||
Integration tests for XMLMappingTool.
|
||||
Use this class for testing interactions between multiple components.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
frappe.ui.form.on('XML Mapping Tool', {
|
||||
refresh: function(frm) {
|
||||
// Инициализация объектов
|
||||
frm.xmlParser = new taxes_az.xml_mapping.XMLParser();
|
||||
frm.fieldGenerator = new taxes_az.xml_mapping.FieldGenerator(frm);
|
||||
frm.doctypeFieldSelector = new taxes_az.xml_mapping.DoctypeFieldSelector(frm);
|
||||
|
||||
// Добавление кнопки для парсинга XML
|
||||
frm.add_custom_button(__('Parse XML'), function() {
|
||||
const xmlContent = frm.doc.xml_sample_file;
|
||||
if (!xmlContent) {
|
||||
frappe.throw(__('Please enter XML content first'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Парсинг XML и создание полей
|
||||
const xmlStructure = frm.xmlParser.parseXML(xmlContent);
|
||||
if (xmlStructure) {
|
||||
// Сохраняем структуру в поле формы
|
||||
frm.set_value('xml_structure', JSON.stringify(xmlStructure));
|
||||
|
||||
// Создаем UI для полей
|
||||
frm.fieldGenerator.createFieldsUI(xmlStructure);
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('XML successfully parsed'),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}).addClass('btn-primary');
|
||||
|
||||
// Если структура XML уже загружена и выбран целевой DocType,
|
||||
// только тогда обновляем UI и только если секция еще не создана
|
||||
if (frm.doc.xml_structure && frm.doc.target_doctype && !$('.xml-mapping-section').length) {
|
||||
try {
|
||||
const xmlStructure = JSON.parse(frm.doc.xml_structure);
|
||||
frm.fieldGenerator.createFieldsUI(xmlStructure);
|
||||
} catch (e) {
|
||||
console.error('Error parsing XML structure:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Добавляем информационное сообщение о процессе использования
|
||||
if (!frm.doc.__islocal) {
|
||||
frm.set_intro(`
|
||||
<div class="alert alert-info">
|
||||
<p><strong>${__('How to use this tool:')}</strong></p>
|
||||
<ol>
|
||||
<li>${__('Paste your XML sample into the XML Content field')}</li>
|
||||
<li>${__('Click "Parse XML" button')}</li>
|
||||
<li>${__('Select a Target DocType')}</li>
|
||||
<li>${__('Map XML fields to DocType fields using the dropdown selectors')}</li>
|
||||
<li>${__('Save your mapping settings by clicking the Save button')}</li>
|
||||
<li>${__('Use the client-side script in your target DocType to add the export button')}</li>
|
||||
</ol>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
// Добавляем кнопку сохранения для явного сохранения маппинга
|
||||
frm.add_custom_button(__('Save Mapping'), function() {
|
||||
frm.save();
|
||||
}).addClass('btn-primary');
|
||||
},
|
||||
|
||||
target_doctype: function(frm) {
|
||||
// При изменении целевого DocType, нам нужно обновить только выпадающие списки,
|
||||
// но не пересоздавать всю секцию
|
||||
if (frm.doc.xml_structure && frm.doc.target_doctype) {
|
||||
try {
|
||||
const xmlStructure = JSON.parse(frm.doc.xml_structure);
|
||||
|
||||
// Если секция уже существует, просто обновим выпадающие списки
|
||||
if ($('.xml-mapping-section').length) {
|
||||
const fieldSelector = new taxes_az.xml_mapping.DoctypeFieldSelector(frm);
|
||||
fieldSelector.attachFieldSelectors($('.xml-fields-container'), xmlStructure.fieldPaths);
|
||||
} else {
|
||||
// Если секции еще нет, создаем полный UI
|
||||
frm.fieldGenerator.createFieldsUI(xmlStructure);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error parsing XML structure:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-04-18 18:47:47.135855",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"tittle",
|
||||
"xml_sample_file",
|
||||
"target_doctype",
|
||||
"is_active",
|
||||
"xml_structure",
|
||||
"mapping_data"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "tittle",
|
||||
"fieldtype": "Data",
|
||||
"label": "Tittle"
|
||||
},
|
||||
{
|
||||
"fieldname": "xml_sample_file",
|
||||
"fieldtype": "Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "XML Sample File"
|
||||
},
|
||||
{
|
||||
"fieldname": "target_doctype",
|
||||
"fieldtype": "Link",
|
||||
"label": "Target Doctype",
|
||||
"options": "DocType"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_active",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is active"
|
||||
},
|
||||
{
|
||||
"fieldname": "xml_structure",
|
||||
"fieldtype": "Long Text",
|
||||
"label": "Xml structure"
|
||||
},
|
||||
{
|
||||
"fieldname": "mapping_data",
|
||||
"fieldtype": "JSON",
|
||||
"label": "Mapping data"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-04-22 12:58:25.456299",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "XML Mapping Tool",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
# taxes_az/taxes_az/doctype/xml_mapping_tool/xml_mapping_tool.py
|
||||
|
||||
import frappe
|
||||
import json
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
class XMLMappingTool(Document):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def generate_xml(mapping_tool, doctype, docname):
|
||||
try:
|
||||
# Получаем документ с правилами маппинга
|
||||
mapping = frappe.get_doc("XML Mapping Tool", mapping_tool)
|
||||
|
||||
# Проверяем наличие необходимых данных
|
||||
if not mapping.xml_sample_file or not mapping.mapping_data:
|
||||
frappe.throw(_("Mapping tool doesn't have sample XML or mapping data"))
|
||||
|
||||
# Получаем данные документа
|
||||
doc_data = frappe.get_doc(doctype, docname)
|
||||
|
||||
# Применяем маппинг для создания XML
|
||||
try:
|
||||
root = ET.fromstring(mapping.xml_sample_file)
|
||||
except Exception as e:
|
||||
frappe.throw(_("Error parsing XML template: {0}").format(str(e)))
|
||||
|
||||
# Загружаем правила маппинга
|
||||
mapping_rules = json.loads(mapping.mapping_data)
|
||||
|
||||
# Применяем правила маппинга
|
||||
for xml_path, field_name in mapping_rules.items():
|
||||
if not field_name:
|
||||
continue
|
||||
|
||||
try:
|
||||
# Получаем значение поля из документа
|
||||
field_value = doc_data.get(field_name)
|
||||
|
||||
# Обрабатываем путь XML
|
||||
if '@' in xml_path: # Это атрибут
|
||||
element_path, attr_name = xml_path.rsplit('@', 1)
|
||||
element_path = element_path.rstrip('/')
|
||||
|
||||
# Находим элемент по пути
|
||||
element = _find_element_by_path(root, element_path)
|
||||
if element is not None:
|
||||
element.set(attr_name, str(field_value) if field_value is not None else '')
|
||||
else: # Это обычный элемент
|
||||
# Находим элемент по пути
|
||||
element = _find_element_by_path(root, xml_path)
|
||||
if element is not None:
|
||||
element.text = str(field_value) if field_value is not None else ''
|
||||
except Exception as e:
|
||||
frappe.log_error(_("Error setting value for {0}: {1}").format(xml_path, str(e)))
|
||||
|
||||
# Конвертируем обратно в строку
|
||||
xml_string = ET.tostring(root, encoding='utf-8', method='xml').decode('utf-8')
|
||||
|
||||
# Добавляем XML декларацию
|
||||
xml_declaration = '<?xml version="1.0" encoding="UTF-8"?>\n'
|
||||
xml_string = xml_declaration + xml_string
|
||||
|
||||
return xml_string
|
||||
except Exception as e:
|
||||
frappe.log_error(_("Error generating XML: {0}").format(str(e)))
|
||||
frappe.throw(_("Error generating XML: {0}").format(str(e)))
|
||||
|
||||
def _find_element_by_path(root, path):
|
||||
"""
|
||||
Находит элемент по пути XPath в XML дереве.
|
||||
Эта функция нужна, поскольку простой root.find() не всегда правильно работает
|
||||
с вложенными путями.
|
||||
"""
|
||||
if not path:
|
||||
return None
|
||||
|
||||
# Удаляем имя корневого элемента из пути, если оно там есть
|
||||
if path.startswith(root.tag + '/'):
|
||||
path = path[len(root.tag) + 1:]
|
||||
|
||||
# Разбиваем путь на компоненты
|
||||
components = path.split('/')
|
||||
|
||||
# Начинаем с корневого элемента
|
||||
current_element = root
|
||||
|
||||
# Проходим по каждому компоненту пути
|
||||
for i, component in enumerate(components):
|
||||
if not component: # Пропускаем пустые компоненты
|
||||
continue
|
||||
|
||||
if component == current_element.tag:
|
||||
# Если текущий компонент соответствует тегу элемента, просто продолжаем
|
||||
continue
|
||||
|
||||
# Для путей с множественными элементами (например, row в HesaplamaUzreEnt)
|
||||
# мы должны найти все подходящие элементы и выбрать нужный
|
||||
# Для простоты, возьмем первый найденный
|
||||
found = False
|
||||
for child in current_element.findall('./'):
|
||||
if child.tag == component:
|
||||
current_element = child
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
# Пробуем найти через XPath напрямую
|
||||
try:
|
||||
result = current_element.find('.//' + component)
|
||||
if result is not None:
|
||||
current_element = result
|
||||
found = True
|
||||
except:
|
||||
pass
|
||||
|
||||
if not found:
|
||||
# Если элемент не найден, возвращаем None
|
||||
return None
|
||||
|
||||
return current_element
|
||||
Loading…
Reference in New Issue