Prepared for VAT form filling
This commit is contained in:
parent
cc48775100
commit
22ff793727
File diff suppressed because it is too large
Load Diff
|
|
@ -1,21 +1,21 @@
|
|||
{
|
||||
"actions": [],
|
||||
"creation": "2025-06-05 14:25:30.955525",
|
||||
"creation": "2025-06-16 21:29:11.777085",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"section_break_t7i9"
|
||||
"section_break_twaq"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "section_break_t7i9",
|
||||
"fieldname": "section_break_twaq",
|
||||
"fieldtype": "Section Break"
|
||||
}
|
||||
],
|
||||
"in_create": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-06-05 14:34:53.228349",
|
||||
"modified": "2025-06-16 21:29:44.750246",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Business Classification",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-06-16 17:05:37.052445",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"activity_type"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "activity_type",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Activity Type",
|
||||
"options": "Main type of activity",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-06-16 17:05:37.052445",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Company Additional Activity",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class CompanyAdditionalActivity(Document):
|
||||
pass
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-06-16 17:05:37.121462",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"organization_name",
|
||||
"organization_tin"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"columns": 8,
|
||||
"fieldname": "organization_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Organization Name",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 4,
|
||||
"fieldname": "organization_tin",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Organization TIN"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-06-18 12:00:00.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Company Affiliate Organization",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class CompanyAffiliateOrganization(Document):
|
||||
pass
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-06-16 17:05:37.233923",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"object_name",
|
||||
"object_code",
|
||||
"object_address",
|
||||
"main_area",
|
||||
"additional_area",
|
||||
"activity_classification",
|
||||
"main_activity_code",
|
||||
"total_employees",
|
||||
"temporary_employees"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "object_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Object Name",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "object_code",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Object Code",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "object_address",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Object Address"
|
||||
},
|
||||
{
|
||||
"fieldname": "main_area",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Main Area (sq.m)"
|
||||
},
|
||||
{
|
||||
"fieldname": "additional_area",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Additional Area (sq.m)"
|
||||
},
|
||||
{
|
||||
"fieldname": "activity_classification",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Activity Classification",
|
||||
"options": "P\u0259rak\u0259nd\u0259 ticar\u0259t\nTopdan ticar\u0259t\n\u0130ctimai ia\u015f\u0259\nEmaledici s\u0259naye\nTikinti\nXidm\u0259t\nDig\u0259r"
|
||||
},
|
||||
{
|
||||
"fieldname": "main_activity_code",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Main Activity Code"
|
||||
},
|
||||
{
|
||||
"fieldname": "total_employees",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Total Employees"
|
||||
},
|
||||
{
|
||||
"fieldname": "temporary_employees",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Temporary Employees"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-06-16 17:05:37.233923",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Company Business Object",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class CompanyBusinessObject(Document):
|
||||
pass
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-06-16 17:05:37.403337",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"certificate_type",
|
||||
"entity_name",
|
||||
"entity_voen",
|
||||
"certificate_series",
|
||||
"certificate_number",
|
||||
"service_value"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "certificate_type",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Certificate Type",
|
||||
"options": "Issued\nReceived",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "entity_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Entity Name",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "entity_voen",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Entity V\u00d6EN",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "certificate_series",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Certificate Series",
|
||||
"length": 3
|
||||
},
|
||||
{
|
||||
"fieldname": "certificate_number",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Certificate Number"
|
||||
},
|
||||
{
|
||||
"description": "Only for received certificates",
|
||||
"fieldname": "service_value",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Service Value"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-06-16 17:05:37.403337",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Company Certificate Data",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class CompanyCertificateData(Document):
|
||||
pass
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-06-16 17:05:37.524930",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"non_resident_name",
|
||||
"country_of_residence",
|
||||
"service_description",
|
||||
"service_period",
|
||||
"foreign_voen",
|
||||
"payment_document_number",
|
||||
"payment_date",
|
||||
"amount_without_vat",
|
||||
"vat_amount"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "non_resident_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Non-Resident Name",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "country_of_residence",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Country of Residence",
|
||||
"options": "T\u00fcrkiy\u0259\nRusiya\nG\u00fcrc\u00fcstan\nAlmaniya\n\u0130ngilt\u0259r\u0259\nAB\u015e\nDig\u0259r",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "service_description",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Service Description",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "service_period",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Service Period"
|
||||
},
|
||||
{
|
||||
"fieldname": "foreign_voen",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Foreign V\u00d6EN"
|
||||
},
|
||||
{
|
||||
"fieldname": "payment_document_number",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Payment Document Number"
|
||||
},
|
||||
{
|
||||
"fieldname": "payment_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Payment Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "amount_without_vat",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount Without VAT",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "vat_amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "VAT Amount",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-06-16 17:05:37.524930",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Company Non Resident Service",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class CompanyNonResidentService(Document):
|
||||
pass
|
||||
|
|
@ -1,33 +1,424 @@
|
|||
// Код для экспорта 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'));
|
||||
// Добавляем кнопку автозаполнения
|
||||
if (!frm.is_new() && frm.doc.docstatus === 0) {
|
||||
frm.add_custom_button(__('Avtomatik Doldur'), function() {
|
||||
fill_declaration_automatically(frm);
|
||||
}, __('Əməliyyatlar'));
|
||||
|
||||
// Стилизуем кнопку
|
||||
frm.page.set_primary_action(__('Avtomatik Doldur'), function() {
|
||||
fill_declaration_automatically(frm);
|
||||
});
|
||||
}
|
||||
|
||||
// Добавляем кнопку проверки
|
||||
if (!frm.is_new()) {
|
||||
frm.add_custom_button(__('Yoxla'), function() {
|
||||
validate_declaration(frm);
|
||||
}, __('Əməliyyatlar'));
|
||||
}
|
||||
|
||||
// Скрываем/показываем вкладки в зависимости от данных
|
||||
toggle_tabs_visibility(frm);
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
// Устанавливаем значения по умолчанию
|
||||
if (frm.is_new()) {
|
||||
set_default_values(frm);
|
||||
}
|
||||
|
||||
// Настраиваем фильтры для полей
|
||||
setup_field_filters(frm);
|
||||
},
|
||||
|
||||
rüb: function(frm) {
|
||||
// При изменении квартала обновляем период
|
||||
update_period_display(frm);
|
||||
},
|
||||
|
||||
il: function(frm) {
|
||||
// При изменении года обновляем период
|
||||
update_period_display(frm);
|
||||
},
|
||||
|
||||
bəyan_ediləcək_məlumatım_yoxdur: function(frm) {
|
||||
// Если отмечено "нет данных для декларирования"
|
||||
if (frm.doc.bəyan_ediləcək_məlumatım_yoxdur) {
|
||||
frappe.confirm(
|
||||
'Bütün məlumatlar silinəcək. Davam etmək istəyirsiniz?',
|
||||
function() {
|
||||
clear_all_tables(frm);
|
||||
},
|
||||
function() {
|
||||
frm.set_value('bəyan_ediləcək_məlumatım_yoxdur', 0);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Функция автоматического заполнения
|
||||
function fill_declaration_automatically(frm) {
|
||||
// Проверяем обязательные поля
|
||||
if (!frm.doc.rüb || !frm.doc.il) {
|
||||
frappe.msgprint({
|
||||
title: __('Xəta'),
|
||||
indicator: 'red',
|
||||
message: __('Zəhmət olmasa rüb və il seçin')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Получаем компанию
|
||||
let company = frm.doc.company || frappe.defaults.get_user_default("Company");
|
||||
|
||||
if (!company) {
|
||||
frappe.msgprint({
|
||||
title: __('Xəta'),
|
||||
indicator: 'red',
|
||||
message: __('Şirkət seçilməyib')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Показываем индикатор загрузки
|
||||
frappe.show_progress('Doldurulur', 30, 100, 'Məlumatlar yüklənir...');
|
||||
|
||||
// Вызываем серверную функцию
|
||||
frappe.call({
|
||||
method: 'taxes_az.declaration_of_value_added_tax.fill_declaration_of_value_added_tax',
|
||||
args: {
|
||||
declaration_name: frm.doc.name,
|
||||
company: company,
|
||||
quarter: frm.doc.rüb,
|
||||
year: frm.doc.il
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.hide_progress();
|
||||
|
||||
if (r.message && r.message.status === 'success') {
|
||||
frm.reload_doc();
|
||||
|
||||
// Показываем результат
|
||||
let msg = `
|
||||
<div>
|
||||
<p><strong>Bəyannamə uğurla dolduruldu!</strong></p>
|
||||
<p>Dövriyyə: ${format_currency(r.message.total_turnover)} AZN</p>
|
||||
<p>Hesablanmış ƏDV: ${format_currency(r.message.total_vat)} AZN</p>
|
||||
<p>Əvəzləşdirilən ƏDV: ${format_currency(r.message.offset_vat)} AZN</p>
|
||||
<hr>
|
||||
<p><strong>${r.message.total_vat_payable >= 0 ? 'Büdcəyə ödənilməli' : 'Büdcədən qaytarılmalı'}:
|
||||
${format_currency(Math.abs(r.message.total_vat_payable))} AZN</strong></p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
frappe.msgprint({
|
||||
title: __('Nəticə'),
|
||||
indicator: 'green',
|
||||
message: msg
|
||||
});
|
||||
|
||||
// Обновляем видимость вкладок
|
||||
toggle_tabs_visibility(frm);
|
||||
} else {
|
||||
frappe.msgprint({
|
||||
title: __('Xəta'),
|
||||
indicator: 'red',
|
||||
message: r.message.message || 'Xəta baş verdi'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(err) {
|
||||
frappe.hide_progress();
|
||||
frappe.msgprint({
|
||||
title: __('Xəta'),
|
||||
indicator: 'red',
|
||||
message: __('Server xətası: ') + err.message
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Функция проверки декларации
|
||||
function validate_declaration(frm) {
|
||||
let errors = [];
|
||||
let warnings = [];
|
||||
|
||||
// Проверка основных данных
|
||||
if (!frm.doc.vöen) {
|
||||
errors.push('VÖEN doldurulmayıb');
|
||||
}
|
||||
|
||||
// Проверка таблиц
|
||||
if (!frm.doc.table_qzfk || frm.doc.table_qzfk.length === 0) {
|
||||
errors.push('Hesabat dövriyyəsi cədvəli boşdur');
|
||||
}
|
||||
|
||||
// Проверка расчетов
|
||||
let total_vat = 0;
|
||||
let offset_vat = 0;
|
||||
|
||||
// Считаем начисленный НДС
|
||||
(frm.doc.table_qzfk || []).forEach(row => {
|
||||
if (row.göstəricilər && row.göstəricilər.startsWith('301')) {
|
||||
total_vat += (row.ədvməbləği || 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Считаем зачетный НДС
|
||||
(frm.doc.table_zvvh || []).forEach(row => {
|
||||
if (row.göstəricilər && row.göstəricilər !== '317. Əməliyyatlar üzrə CƏMİ') {
|
||||
offset_vat += (row.əlavədəyərvergisininməbləği || 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Проверка итоговой строки
|
||||
let has_payable = false;
|
||||
let has_refund = false;
|
||||
|
||||
(frm.doc.table_kyya || []).forEach(row => {
|
||||
if (row.göstəricilər === '326. Büdcəyə ödənilməlidir') {
|
||||
has_payable = true;
|
||||
if (row.ədvməbləği !== (total_vat - offset_vat)) {
|
||||
errors.push('Büdcəyə ödənilməli məbləğ düzgün hesablanmayıb');
|
||||
}
|
||||
}
|
||||
if (row.göstəricilər === '327. Büdcədən qaytarılır') {
|
||||
has_refund = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (has_payable && has_refund) {
|
||||
errors.push('Həm ödəniş, həm də qaytarma eyni vaxtda ola bilməz');
|
||||
}
|
||||
|
||||
// Проверка приложений
|
||||
if (frm.doc.table_gpfh && frm.doc.table_gpfh.length > 0) {
|
||||
frm.doc.table_gpfh.forEach((row, idx) => {
|
||||
if (!row.obyektinadı || !row.obyektinünvanı) {
|
||||
warnings.push(`Əlavə 9: Sətir ${idx + 1} - obyekt məlumatları natamamdır`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Показываем результаты
|
||||
show_validation_results(errors, warnings);
|
||||
}
|
||||
|
||||
// Установка значений по умолчанию
|
||||
function set_default_values(frm) {
|
||||
// Текущий квартал
|
||||
let current_month = frappe.datetime.now_date().getMonth() + 1;
|
||||
let current_quarter = Math.ceil(current_month / 3);
|
||||
let quarter_map = {1: '1. Rüb', 2: '2. Rüb', 3: '3. Rüb', 4: '4. Rüb'};
|
||||
|
||||
frm.set_value('rüb', quarter_map[current_quarter]);
|
||||
frm.set_value('il', frappe.datetime.now_date().getFullYear());
|
||||
frm.set_value('vergidövrü', 'Rüblük');
|
||||
frm.set_value('bəyannaməninnövü', 'Cari');
|
||||
|
||||
// Данные компании
|
||||
let company = frappe.defaults.get_user_default("Company");
|
||||
if (company) {
|
||||
frappe.db.get_doc('Company', company).then(doc => {
|
||||
frm.set_value('vöen', doc.tax_id);
|
||||
frm.set_value('ödəyicitipi', doc.taxpayer_type || 'Hüquqi');
|
||||
frm.set_value('vergininödəyicisininqrupu', doc.taxpayer_group);
|
||||
frm.set_value('vergiödəyisininqrupu', doc.tax_payment_group);
|
||||
frm.set_value('vergiorqanı', doc.tax_authority);
|
||||
frm.set_value('valyutanınnövü', 'Azərbaycan manatı');
|
||||
|
||||
// НДС регистрация
|
||||
if (doc.vat_registration_date) {
|
||||
frm.set_value('ədvqeydiyyatınınqüvəyyəminmətarixi',
|
||||
frappe.datetime.str_to_user(doc.vat_registration_date).replace(/-/g, ''));
|
||||
}
|
||||
if (doc.vat_certificate_number) {
|
||||
frm.set_value('ədvbildirişininnsi', doc.vat_certificate_number);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Настройка фильтров
|
||||
function setup_field_filters(frm) {
|
||||
// Фильтр для выбора месяца в зависимости от квартала
|
||||
frm.set_query('ay', function() {
|
||||
let quarter_months = {
|
||||
'1. Rüb': ['Yanvar', 'Fevral', 'Mart'],
|
||||
'2. Rüb': ['Aprel', 'May', 'İyun'],
|
||||
'3. Rüb': ['İyul', 'Avqust', 'Sentyabr'],
|
||||
'4. Rüb': ['Oktyabr', 'Noyabr', 'Dekabr']
|
||||
};
|
||||
|
||||
return {
|
||||
filters: [
|
||||
['name', 'in', quarter_months[frm.doc.rüb] || []]
|
||||
]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// Скрытие/показ вкладок
|
||||
function toggle_tabs_visibility(frm) {
|
||||
// Скрываем все вкладки приложений по умолчанию
|
||||
let all_appendices = [
|
||||
'əlavə_1_tab', 'əlavə_2_tab', 'əlavə_3_tab', 'əlavə_4_tab',
|
||||
'əlavə_5_tab', 'əlavə_6_tab', 'əlavə_7_tab', 'əlavə_8_tab',
|
||||
'əlavə_9_tab', 'əlavə_10_tab'
|
||||
];
|
||||
|
||||
all_appendices.forEach(tab => {
|
||||
frm.toggle_display(tab, false);
|
||||
});
|
||||
|
||||
// Показываем только заполненные
|
||||
// Приложение 3 - всегда для услуг
|
||||
if (frm.doc.table_kdll && frm.doc.table_kdll.length > 0) {
|
||||
frm.toggle_display('əlavə_3_tab', true);
|
||||
}
|
||||
|
||||
// Приложение 7 - услуги нерезидентов
|
||||
if (frm.doc.table_vonn && frm.doc.table_vonn.length > 0) {
|
||||
frm.toggle_display('əlavə_7_tab', true);
|
||||
}
|
||||
|
||||
// Приложение 9 - объекты
|
||||
if (frm.doc.table_gpfh && frm.doc.table_gpfh.length > 0) {
|
||||
frm.toggle_display('əlavə_9_tab', true);
|
||||
}
|
||||
}
|
||||
|
||||
// Обновление отображения периода
|
||||
function update_period_display(frm) {
|
||||
if (frm.doc.rüb && frm.doc.il) {
|
||||
let period_text = `${frm.doc.il}-ci il, ${frm.doc.rüb}`;
|
||||
frm.set_intro(period_text);
|
||||
}
|
||||
}
|
||||
|
||||
// Очистка всех таблиц
|
||||
function clear_all_tables(frm) {
|
||||
let tables = [
|
||||
'table_qzfk', 'table_ufli', 'table_zvvh', 'table_wtjt',
|
||||
'table_kyya', 'table_ftqr', 'table_rsid', 'table_vliw',
|
||||
'table_fdbw', 'table_anob', 'table_kdll', 'table_pycw',
|
||||
'table_hnwx', 'table_bchc', 'table_vonn', 'table_gpfh',
|
||||
'table_bgay', 'table_hnbv', 'table_kmis', 'table_twws'
|
||||
];
|
||||
|
||||
tables.forEach(table => {
|
||||
frm.clear_table(table);
|
||||
});
|
||||
|
||||
frm.refresh_fields();
|
||||
frappe.show_alert({
|
||||
message: __('Bütün cədvəllər təmizləndi'),
|
||||
indicator: 'blue'
|
||||
});
|
||||
}
|
||||
|
||||
// Показ результатов валидации
|
||||
function show_validation_results(errors, warnings) {
|
||||
let html = '<div>';
|
||||
|
||||
if (errors.length > 0) {
|
||||
html += '<h4 style="color: red;">Xətalar:</h4><ul>';
|
||||
errors.forEach(err => {
|
||||
html += `<li>${err}</li>`;
|
||||
});
|
||||
html += '</ul>';
|
||||
}
|
||||
|
||||
if (warnings.length > 0) {
|
||||
html += '<h4 style="color: orange;">Xəbərdarlıqlar:</h4><ul>';
|
||||
warnings.forEach(warn => {
|
||||
html += `<li>${warn}</li>`;
|
||||
});
|
||||
html += '</ul>';
|
||||
}
|
||||
|
||||
if (errors.length === 0 && warnings.length === 0) {
|
||||
html += '<p style="color: green;">Heç bir xəta tapılmadı!</p>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
||||
frappe.msgprint({
|
||||
title: __('Yoxlama nəticəsi'),
|
||||
indicator: errors.length > 0 ? 'red' : (warnings.length > 0 ? 'orange' : 'green'),
|
||||
message: html
|
||||
});
|
||||
}
|
||||
|
||||
// Форматирование валюты
|
||||
function format_currency(amount) {
|
||||
return frappe.format(amount, {fieldtype: 'Currency', currency: 'AZN'});
|
||||
}
|
||||
|
||||
// Дополнительные обработчики для таблиц
|
||||
frappe.ui.form.on('Declaration of value added tax Hesabat Dovriyye uzre', {
|
||||
ədvməbləği: function(frm, cdt, cdn) {
|
||||
calculate_totals(frm);
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Declaration of value added tax Evezlesdirilen', {
|
||||
əlavədəyərvergisininməbləği: function(frm, cdt, cdn) {
|
||||
calculate_totals(frm);
|
||||
}
|
||||
});
|
||||
|
||||
// Пересчет итогов
|
||||
function calculate_totals(frm) {
|
||||
let total_vat = 0;
|
||||
let offset_vat = 0;
|
||||
|
||||
// Считаем начисленный НДС
|
||||
(frm.doc.table_qzfk || []).forEach(row => {
|
||||
if (row.göstəricilər && row.göstəricilər.startsWith('301')) {
|
||||
total_vat += (row.ədvməbləği || 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Считаем зачетный НДС
|
||||
(frm.doc.table_zvvh || []).forEach(row => {
|
||||
if (row.göstəricilər && row.göstəricilər !== '317. Əməliyyatlar üzrə CƏMİ') {
|
||||
offset_vat += (row.əlavədəyərvergisininməbləği || 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Обновляем итоговую таблицу
|
||||
let net_vat = total_vat - offset_vat;
|
||||
|
||||
// Очищаем таблицу расчетов
|
||||
frm.clear_table('table_kyya');
|
||||
|
||||
if (net_vat > 0) {
|
||||
frm.add_child('table_kyya', {
|
||||
göstəricilər: '326. Büdcəyə ödənilməlidir',
|
||||
ədvməbləği: net_vat
|
||||
});
|
||||
} else if (net_vat < 0) {
|
||||
frm.add_child('table_kyya', {
|
||||
göstəricilər: '327. Büdcədən qaytarılır',
|
||||
ədvməbləği: Math.abs(net_vat)
|
||||
});
|
||||
}
|
||||
|
||||
frm.refresh_field('table_kyya');
|
||||
}
|
||||
|
||||
// Горячие клавиши
|
||||
frappe.ui.keys.add_shortcut({
|
||||
shortcut: 'ctrl+shift+f',
|
||||
action: () => {
|
||||
let frm = cur_frm;
|
||||
if (frm && frm.doc.doctype === 'Declaration of value added tax') {
|
||||
fill_declaration_automatically(frm);
|
||||
}
|
||||
},
|
||||
description: __('Avtomatik doldur')
|
||||
});
|
||||
|
|
@ -1,9 +1,381 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# Copyright (c) 2025, Your Company and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate, add_months, cint
|
||||
from datetime import datetime, date
|
||||
import calendar
|
||||
|
||||
class Declarationofvalueaddedtax(Document):
|
||||
pass
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from datetime import datetime, date
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import json
|
||||
|
||||
@frappe.whitelist()
|
||||
def fill_vat_declaration(declaration_name, company, quarter, year):
|
||||
"""
|
||||
Автоматическое заполнение НДС декларации для компании разработки ПО
|
||||
"""
|
||||
# Получаем документ декларации
|
||||
doc = frappe.get_doc("Declaration of value added tax", declaration_name)
|
||||
|
||||
# Определяем период (начало и конец квартала)
|
||||
quarter_start, quarter_end = get_quarter_dates(quarter, year)
|
||||
|
||||
# Основные данные компании
|
||||
company_doc = frappe.get_doc("Company", company)
|
||||
|
||||
# 1. ЗАПОЛНЯЕМ ОСНОВНУЮ ЧАСТЬ ДЕКЛАРАЦИИ
|
||||
|
||||
# Получаем доходы от разработки ПО (Sales Invoice)
|
||||
software_income = get_software_development_income(company, quarter_start, quarter_end)
|
||||
|
||||
# Получаем входящий НДС (Purchase Invoice)
|
||||
input_vat = get_input_vat(company, quarter_start, quarter_end)
|
||||
|
||||
# Заполняем основную таблицу "Hesabat dövründəki dövriyyə üzrə"
|
||||
fill_main_turnover_table(doc, software_income, input_vat)
|
||||
|
||||
# 2. ЗАПОЛНЯЕМ ПРИЛОЖЕНИЕ 3 (Əlavə 3)
|
||||
fill_appendix_3(doc, software_income, quarter_start, quarter_end)
|
||||
|
||||
# 3. ЗАПОЛНЯЕМ ПРИЛОЖЕНИЕ 7 (если есть услуги от нерезидентов)
|
||||
non_resident_services = get_non_resident_services(company, quarter_start, quarter_end)
|
||||
if non_resident_services:
|
||||
fill_appendix_7(doc, non_resident_services)
|
||||
|
||||
# 4. ЗАПОЛНЯЕМ ПРИЛОЖЕНИЕ 9 (офисы)
|
||||
fill_appendix_9(doc, company_doc)
|
||||
|
||||
# Сохраняем документ
|
||||
doc.save()
|
||||
frappe.db.commit()
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"message": f"НДС декларация заполнена за {quarter} квартал {year} года",
|
||||
"total_vat_payable": calculate_vat_payable(doc)
|
||||
}
|
||||
|
||||
def get_quarter_dates(quarter, year):
|
||||
"""Получаем даты начала и конца квартала"""
|
||||
quarter_map = {
|
||||
"1. Rüb": (1, 3),
|
||||
"2. Rüb": (4, 6),
|
||||
"3. Rüb": (7, 9),
|
||||
"4. Rüb": (10, 12)
|
||||
}
|
||||
|
||||
start_month, end_month = quarter_map[quarter]
|
||||
quarter_start = date(year, start_month, 1)
|
||||
quarter_end = date(year, end_month, 1) + relativedelta(months=1) - relativedelta(days=1)
|
||||
|
||||
return quarter_start, quarter_end
|
||||
|
||||
def get_software_development_income(company, start_date, end_date):
|
||||
"""Получаем доходы от разработки ПО"""
|
||||
# Выбираем все Sales Invoice за период
|
||||
invoices = frappe.db.sql("""
|
||||
SELECT
|
||||
si.name,
|
||||
si.customer,
|
||||
si.total,
|
||||
si.total_taxes_and_charges,
|
||||
si.grand_total,
|
||||
si.posting_date,
|
||||
si.is_pos,
|
||||
si.mode_of_payment
|
||||
FROM `tabSales Invoice` si
|
||||
WHERE si.company = %s
|
||||
AND si.posting_date BETWEEN %s AND %s
|
||||
AND si.docstatus = 1
|
||||
AND si.is_return = 0
|
||||
""", (company, start_date, end_date), as_dict=True)
|
||||
|
||||
# Группируем по типам операций
|
||||
result = {
|
||||
"total_without_vat": 0,
|
||||
"total_vat": 0,
|
||||
"cash_sales": 0,
|
||||
"cashless_sales": 0,
|
||||
"pos_sales": 0,
|
||||
"invoices": invoices
|
||||
}
|
||||
|
||||
for inv in invoices:
|
||||
# Сумма без НДС
|
||||
base_amount = inv.total or 0
|
||||
vat_amount = inv.total_taxes_and_charges or 0
|
||||
|
||||
result["total_without_vat"] += base_amount
|
||||
result["total_vat"] += vat_amount
|
||||
|
||||
# Определяем тип оплаты
|
||||
if inv.is_pos:
|
||||
result["pos_sales"] += base_amount
|
||||
elif inv.mode_of_payment and "cash" in inv.mode_of_payment.lower():
|
||||
result["cash_sales"] += base_amount
|
||||
else:
|
||||
result["cashless_sales"] += base_amount
|
||||
|
||||
return result
|
||||
|
||||
def get_input_vat(company, start_date, end_date):
|
||||
"""Получаем входящий НДС"""
|
||||
purchases = frappe.db.sql("""
|
||||
SELECT
|
||||
pi.name,
|
||||
pi.supplier,
|
||||
pi.total,
|
||||
pi.total_taxes_and_charges,
|
||||
pi.grand_total,
|
||||
pi.posting_date,
|
||||
s.supplier_type,
|
||||
s.country
|
||||
FROM `tabPurchase Invoice` pi
|
||||
LEFT JOIN `tabSupplier` s ON pi.supplier = s.name
|
||||
WHERE pi.company = %s
|
||||
AND pi.posting_date BETWEEN %s AND %s
|
||||
AND pi.docstatus = 1
|
||||
AND pi.is_return = 0
|
||||
""", (company, start_date, end_date), as_dict=True)
|
||||
|
||||
result = {
|
||||
"total_without_vat": 0,
|
||||
"total_vat": 0,
|
||||
"resident_purchases": 0,
|
||||
"resident_vat": 0,
|
||||
"non_resident_purchases": 0,
|
||||
"non_resident_vat": 0,
|
||||
"purchases": purchases
|
||||
}
|
||||
|
||||
for pur in purchases:
|
||||
base_amount = pur.total or 0
|
||||
vat_amount = pur.total_taxes_and_charges or 0
|
||||
|
||||
result["total_without_vat"] += base_amount
|
||||
result["total_vat"] += vat_amount
|
||||
|
||||
# Определяем резидент или нет
|
||||
if pur.country and pur.country != "Azerbaijan":
|
||||
result["non_resident_purchases"] += base_amount
|
||||
result["non_resident_vat"] += vat_amount
|
||||
else:
|
||||
result["resident_purchases"] += base_amount
|
||||
result["resident_vat"] += vat_amount
|
||||
|
||||
return result
|
||||
|
||||
def fill_main_turnover_table(doc, income_data, input_vat_data):
|
||||
"""Заполняем основную таблицу по обороту"""
|
||||
# Очищаем существующие строки
|
||||
doc.table_qzfk = []
|
||||
|
||||
# 301 - ƏDV-nə 18 faiz dərəcə ilə cəlb olunan əməliyyatlar
|
||||
doc.append("table_qzfk", {
|
||||
"göstəricilər": "301. ƏDV-nə 18 faiz dərəcə ilə cəlb olunan əməliyyatlar",
|
||||
"təqdimedilmişmalişvəxidmətlərindəyəriədvnəzərəalınmadan": 0,
|
||||
"daxilolmuşməbləğədvnəzərəalınmadan": 0,
|
||||
"ədvməbləği": 0
|
||||
})
|
||||
|
||||
# 301.1 - Malların təqdim edilməsi, işlərin görülməsi, xidmətlərin göstərilməsi
|
||||
doc.append("table_qzfk", {
|
||||
"göstəricilər": "301.1 Malların təqdim edilməsi, işlərin görülməsi, xidmətlərin göstərilməsi üzrə əməliyyatlar",
|
||||
"təqdimedilmişmalişvəxidmətlərindəyəriədvnəzərəalınmadan": income_data["total_without_vat"],
|
||||
"daxilolmuşməbləğədvnəzərəalınmadan": income_data["total_without_vat"], # Для услуг обычно равны
|
||||
"ədvməbləği": income_data["total_vat"]
|
||||
})
|
||||
|
||||
# 305 - Əməliyyatlar üzrə CƏMİ
|
||||
total_turnover = income_data["total_without_vat"]
|
||||
total_received = income_data["total_without_vat"]
|
||||
total_vat = income_data["total_vat"]
|
||||
|
||||
doc.append("table_qzfk", {
|
||||
"göstəricilər": "305. Əməliyyatlar üzrə CƏMİ",
|
||||
"təqdimedilmişmalişvəxidmətlərindəyəriədvnəzərəalınmadan": total_turnover,
|
||||
"daxilolmuşməbləğədvnəzərəalınmadan": total_received,
|
||||
"ədvməbləği": total_vat
|
||||
})
|
||||
|
||||
# Заполняем таблицу Əvəzləşdirilən (зачеты)
|
||||
doc.table_zvvh = []
|
||||
|
||||
# 308 - Электронные счета-фактуры
|
||||
if input_vat_data["resident_vat"] > 0:
|
||||
doc.append("table_zvvh", {
|
||||
"göstəricilər": "308. VM 175.1-ci maddəsinə əsasən alınmış elektron qaimə-fakturalar (elektron vergi hesab-fakturalar) üzrə nağdsız qaydada ödənilmiş məbləğ",
|
||||
"ödənilmişməbləğədvnəzərəalınmadan": input_vat_data["resident_purchases"],
|
||||
"əlavədəyərvergisininməbləği": input_vat_data["resident_vat"]
|
||||
})
|
||||
|
||||
# 312 - Платежи нерезидентам (если есть)
|
||||
if input_vat_data["non_resident_vat"] > 0:
|
||||
doc.append("table_zvvh", {
|
||||
"göstəricilər": "312. Vergi Məcəlləsinin 169.4-cü maddəsinə əsasən qeyri-rezidentə ödənilmiş məbləğ",
|
||||
"ödənilmişməbləğədvnəzərəalınmadan": input_vat_data["non_resident_purchases"],
|
||||
"əlavədəyərvergisininməbləği": input_vat_data["non_resident_vat"]
|
||||
})
|
||||
|
||||
# 317 - Итого по зачетам
|
||||
doc.append("table_zvvh", {
|
||||
"göstəricilər": "317. Əməliyyatlar üzrə CƏMİ",
|
||||
"ödənilmişməbləğədvnəzərəalınmadan": input_vat_data["total_without_vat"],
|
||||
"əlavədəyərvergisininməbləği": input_vat_data["total_vat"]
|
||||
})
|
||||
|
||||
# Заполняем Hesablaşmalar (расчеты с бюджетом)
|
||||
doc.table_kyya = []
|
||||
|
||||
vat_payable = total_vat - input_vat_data["total_vat"]
|
||||
|
||||
if vat_payable > 0:
|
||||
# 326 - К уплате в бюджет
|
||||
doc.append("table_kyya", {
|
||||
"göstəricilər": "326. Büdcəyə ödənilməlidir",
|
||||
"ədvməbləği": vat_payable
|
||||
})
|
||||
else:
|
||||
# 327 - К возврату из бюджета
|
||||
doc.append("table_kyya", {
|
||||
"göstəricilər": "327. Büdcədən qaytarılır",
|
||||
"ədvməbləği": abs(vat_payable)
|
||||
})
|
||||
|
||||
def fill_appendix_3(doc, income_data, start_date, end_date):
|
||||
"""Заполняем Приложение 3 - детализация операций"""
|
||||
# Таблица 1 - ƏDV tutulan dövriyyə
|
||||
doc.table_kdll = []
|
||||
|
||||
# 301.1.2.6 - Прочие услуги (разработка ПО)
|
||||
doc.append("table_kdll", {
|
||||
"göstəricilər": "301.1.2.6 Sair işlərin görülməsi və xidmətlərin göstərilməsi üzrə əməliyyatlar",
|
||||
"təqdimedilmişmalişvəxidmətlərindəyəriədvnəzərəalınmadan": income_data["total_without_vat"],
|
||||
"daxilolmuşməbləğədvnəzərəalınmadan": income_data["total_without_vat"]
|
||||
})
|
||||
|
||||
def fill_appendix_7(doc, non_resident_services):
|
||||
"""Заполняем Приложение 7 - услуги нерезидентов"""
|
||||
doc.table_vonn = []
|
||||
|
||||
for service in non_resident_services:
|
||||
doc.append("table_vonn", {
|
||||
"qeyrirezidentinadı": service["supplier_name"],
|
||||
"rezidentolduğuölkəninadı": service["country"],
|
||||
"görülmüşişinxidmətinadı": service["service_description"],
|
||||
"görülmüşişindövrü": service["service_period"],
|
||||
"rezidentolduğuölkədəkivöeni": service["foreign_tax_id"],
|
||||
"büdcəyəödənişitəsdiqtəsdiqedənsənədinnsi": service["payment_doc_no"],
|
||||
"sənədintarixi": service["payment_date"],
|
||||
"ödənilmişümumiədvsizməbləği": service["amount_without_vat"],
|
||||
"ödənilmişümumiədvməbləği": service["vat_amount"]
|
||||
})
|
||||
|
||||
def fill_appendix_9(doc, company_doc):
|
||||
"""Заполняем Приложение 9 - данные об офисах"""
|
||||
doc.table_gpfh = []
|
||||
|
||||
# Получаем офисы из business_objects компании
|
||||
if company_doc.business_objects:
|
||||
for idx, obj in enumerate(company_doc.business_objects):
|
||||
doc.append("table_gpfh", {
|
||||
"sətrinkodu": idx + 1,
|
||||
"obyektinadı": obj.object_name,
|
||||
"obyektinkodu": obj.object_code,
|
||||
"obyektinünvanı": obj.address,
|
||||
"obyektinəsassahəsikvm": obj.main_area,
|
||||
"obyektinəlavəsahəsikvm": obj.additional_area,
|
||||
"obyektinfəaliyyətsahəsiüzrətəsnifatı": "İXTİSASLI, ELMİ VƏ TEXNİKİ FƏALİYYƏT",
|
||||
"obyektinəsasfəaliyyətnövününkoduvəadı": "J62010 - Kompüter proqramlaşdırma fəaliyyəti",
|
||||
"obyektüzrəişçilərincəmisayı": obj.total_employees,
|
||||
"ocümlədənobyektüzrəmüvəqqətiişçilərinsayı": obj.temporary_employees,
|
||||
"obyektüzrətəqdimedilmişmallarınişlərinxidmətlərindəyərimanatla": obj.turnover,
|
||||
"obyekttəqdimedilmişmallaraəldəedilmişhasilatməbləği": obj.revenue
|
||||
})
|
||||
|
||||
def get_non_resident_services(company, start_date, end_date):
|
||||
"""Получаем услуги от нерезидентов"""
|
||||
# Здесь нужно определить логику получения услуг от нерезидентов
|
||||
# Например, из Purchase Invoice где поставщик - нерезидент
|
||||
|
||||
services = frappe.db.sql("""
|
||||
SELECT
|
||||
pi.name,
|
||||
pi.supplier,
|
||||
s.supplier_name,
|
||||
s.country,
|
||||
pi.total as amount_without_vat,
|
||||
pi.total_taxes_and_charges as vat_amount,
|
||||
pi.posting_date,
|
||||
pi.bill_no
|
||||
FROM `tabPurchase Invoice` pi
|
||||
JOIN `tabSupplier` s ON pi.supplier = s.name
|
||||
WHERE pi.company = %s
|
||||
AND pi.posting_date BETWEEN %s AND %s
|
||||
AND pi.docstatus = 1
|
||||
AND s.country != 'Azerbaijan'
|
||||
AND s.country IS NOT NULL
|
||||
""", (company, start_date, end_date), as_dict=True)
|
||||
|
||||
result = []
|
||||
for service in services:
|
||||
result.append({
|
||||
"supplier_name": service.supplier_name,
|
||||
"country": service.country,
|
||||
"service_description": "IT услуги", # Можно брать из описания в PI
|
||||
"service_period": service.posting_date.strftime("%Y%m"),
|
||||
"foreign_tax_id": "", # Нужно добавить поле в Supplier
|
||||
"payment_doc_no": service.bill_no or service.name,
|
||||
"payment_date": service.posting_date.strftime("%Y%m%d"),
|
||||
"amount_without_vat": service.amount_without_vat,
|
||||
"vat_amount": service.vat_amount or (service.amount_without_vat * 0.18)
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
def calculate_vat_payable(doc):
|
||||
"""Рассчитываем НДС к уплате"""
|
||||
# Берем из таблицы Hesablaşmalar
|
||||
for row in doc.table_kyya:
|
||||
if row.göstəricilər == "326. Büdcəyə ödənilməlidir":
|
||||
return row.ədvməbləği
|
||||
elif row.göstəricilər == "327. Büdcədən qaytarılır":
|
||||
return -row.ədvməbləği
|
||||
return 0
|
||||
|
||||
# Функция для вызова из UI
|
||||
@frappe.whitelist()
|
||||
def create_and_fill_vat_declaration(company, quarter, year):
|
||||
"""Создать и заполнить НДС декларацию"""
|
||||
# Создаем новый документ
|
||||
doc = frappe.new_doc("Declaration of value added tax")
|
||||
|
||||
# Базовые поля
|
||||
doc.vergidövrü = "Rüblük"
|
||||
doc.rüb = quarter
|
||||
doc.il = int(year)
|
||||
|
||||
# Данные компании
|
||||
company_doc = frappe.get_doc("Company", company)
|
||||
doc.vöen = company_doc.tax_id
|
||||
doc.adı = company_doc.company_name
|
||||
doc.vergiorqanı = company_doc.tax_authority or "Dövlət Vergi xidmətinin Bakı şəhəri Kiçik Sahibkarlıqla İş üzrə Baş idarəsi"
|
||||
|
||||
# Сохраняем документ
|
||||
doc.insert()
|
||||
|
||||
# Заполняем данными
|
||||
result = fill_vat_declaration(doc.name, company, quarter, year)
|
||||
|
||||
return {
|
||||
"declaration_name": doc.name,
|
||||
"result": result
|
||||
}
|
||||
Loading…
Reference in New Issue