diff --git a/taxes_az/taxes_az/doctype/tax_article/tax_article.js b/taxes_az/taxes_az/doctype/tax_article/tax_article.js index f5398cc..9e6f0fc 100644 --- a/taxes_az/taxes_az/doctype/tax_article/tax_article.js +++ b/taxes_az/taxes_az/doctype/tax_article/tax_article.js @@ -1,8 +1,120 @@ -// Copyright (c) 2025, Jey Soft and contributors -// For license information, please see license.txt +frappe.ui.form.on('Tax Article', { + // Инициализация: сохраняем начальные значения + refresh: function(frm) { + store_last_values(frm); + }, + + // При изменении date_from + date_from: function(frm) { + if (!frm._is_calculating) { + frm._is_calculating = true; + + if (frm.doc.date_from && frm.doc.date_to) { + // Если есть date_to, всегда пересчитываем duration + calculate_duration(frm); + + // Валидация + validate_dates(frm); + } + + store_last_values(frm); + frm._is_calculating = false; + } + }, + + // При изменении date_to + date_to: function(frm) { + if (!frm._is_calculating) { + frm._is_calculating = true; + + if (frm.doc.date_to && frm.doc.date_from) { + // Валидация + if (validate_dates(frm)) { + // Пересчитываем duration + calculate_duration(frm); + } + } + + store_last_values(frm); + frm._is_calculating = false; + } + }, + + // При изменении duration + duration: function(frm) { + if (!frm._is_calculating) { + frm._is_calculating = true; + + if (frm.doc.duration && frm.doc.date_from) { + // Пересчитываем date_to + calculate_date_to(frm); + + // Валидация + validate_dates(frm); + } + + store_last_values(frm); + frm._is_calculating = false; + } + }, + + // Валидация перед сохранением + validate: function(frm) { + if (frm.doc.date_from && frm.doc.date_to) { + validate_dates(frm); + } + } +}); -// frappe.ui.form.on("Tax Article", { -// refresh(frm) { +// Рассчитать date_to на основе date_from и duration +function calculate_date_to(frm) { + if (!frm.doc.date_from || !frm.doc.duration) return; + + let from_date = frappe.datetime.str_to_obj(frm.doc.date_from); + let to_date = new Date(from_date); + to_date.setFullYear(to_date.getFullYear() + frm.doc.duration); + + frm.set_value('date_to', frappe.datetime.obj_to_str(to_date)); +} -// }, -// }); +// Рассчитать duration на основе date_from и date_to +function calculate_duration(frm) { + if (!frm.doc.date_from || !frm.doc.date_to) return; + + let from_date = frappe.datetime.str_to_obj(frm.doc.date_from); + let to_date = frappe.datetime.str_to_obj(frm.doc.date_to); + + // Рассчитываем разницу в годах + let years = (to_date - from_date) / (365.25 * 24 * 60 * 60 * 1000); + let rounded_years = Math.round(years); + + frm.set_value('duration', rounded_years); +} + +// Валидация: date_to должна быть >= date_from +function validate_dates(frm) { + if (!frm.doc.date_from || !frm.doc.date_to) return true; + + let from_date = frappe.datetime.str_to_obj(frm.doc.date_from); + let to_date = frappe.datetime.str_to_obj(frm.doc.date_to); + + if (to_date < from_date) { + frappe.msgprint({ + title: __('Invalid Date Range'), + indicator: 'red', + message: __('Date To cannot be earlier than Date From') + }); + return false; + } + + return true; +} + +// Сохранить текущие значения полей +function store_last_values(frm) { + frm._last_values = { + date_from: frm.doc.date_from, + date_to: frm.doc.date_to, + duration: frm.doc.duration + }; +} \ No newline at end of file diff --git a/taxes_az/taxes_az/doctype/tax_article/tax_article.json b/taxes_az/taxes_az/doctype/tax_article/tax_article.json index a34bbe4..eeb1851 100644 --- a/taxes_az/taxes_az/doctype/tax_article/tax_article.json +++ b/taxes_az/taxes_az/doctype/tax_article/tax_article.json @@ -14,7 +14,12 @@ "lft", "rgt", "is_group", - "old_parent" + "old_parent", + "validity_period", + "date_from", + "duration", + "column_break_zcwq", + "date_to" ], "fields": [ { @@ -27,8 +32,7 @@ "fieldtype": "Text", "in_list_view": 1, "label": "Article Name", - "reqd": 1, - "unique": 1 + "reqd": 1 }, { "description": "Declaration text for tax article", @@ -45,19 +49,19 @@ { "fieldname": "lft", "fieldtype": "Float", - "precision": "2", "hidden": 1, "label": "Left", "no_copy": 1, + "precision": "2", "read_only": 1 }, { "fieldname": "rgt", "fieldtype": "Float", - "precision": "2", "hidden": 1, "label": "Right", "no_copy": 1, + "precision": "2", "read_only": 1 }, { @@ -72,12 +76,36 @@ "ignore_user_permissions": 1, "label": "Parent Tax Article", "options": "Tax Article" + }, + { + "fieldname": "validity_period", + "fieldtype": "Section Break", + "label": "Validity Period" + }, + { + "fieldname": "date_from", + "fieldtype": "Date", + "label": "Date From" + }, + { + "fieldname": "duration", + "fieldtype": "Int", + "label": "Duration" + }, + { + "fieldname": "column_break_zcwq", + "fieldtype": "Column Break" + }, + { + "fieldname": "date_to", + "fieldtype": "Date", + "label": "Date To" } ], "index_web_pages_for_search": 1, "is_tree": 1, "links": [], - "modified": "2025-08-26 19:56:54.264329", + "modified": "2025-10-31 17:17:26.936793", "modified_by": "Administrator", "module": "Taxes Az", "name": "Tax Article", @@ -98,7 +126,8 @@ "write": 1 } ], + "row_format": "Dynamic", "sort_field": "creation", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/taxes_az/taxes_az/doctype/tax_article/tax_article.py b/taxes_az/taxes_az/doctype/tax_article/tax_article.py index 3f9044f..4773321 100644 --- a/taxes_az/taxes_az/doctype/tax_article/tax_article.py +++ b/taxes_az/taxes_az/doctype/tax_article/tax_article.py @@ -1,8 +1,17 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2025, Your Company and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals import frappe from frappe.model.document import Document +from frappe.utils import getdate, add_years class TaxArticle(Document): def autoname(self): + """ + Auto-generate document name from article_name + """ if not self.article_name: return @@ -21,4 +30,45 @@ class TaxArticle(Document): name = original_name[:max_length] + suffix counter += 1 - self.name = name \ No newline at end of file + self.name = name + + def validate(self): + """ + Validate Tax Article fields and auto-calculate missing values + """ + # Автоматический расчет полей + self.auto_calculate_validity_fields() + + # Валидация дат + self.validate_date_range() + + def auto_calculate_validity_fields(self): + """ + Auto-calculate missing validity fields based on available data + """ + # Если есть date_from и duration, но нет date_to + if self.date_from and self.duration and not self.date_to: + self.date_to = add_years(getdate(self.date_from), self.duration) + + # Если есть date_from и date_to, но нет duration + elif self.date_from and self.date_to and not self.duration: + from_date = getdate(self.date_from) + to_date = getdate(self.date_to) + + # Рассчитываем разницу в годах + years = (to_date - from_date).days / 365.25 + self.duration = round(years) + + def validate_date_range(self): + """ + Validate that date_to is not earlier than date_from + """ + if self.date_from and self.date_to: + from_date = getdate(self.date_from) + to_date = getdate(self.date_to) + + if to_date < from_date: + frappe.throw( + frappe._("Date To cannot be earlier than Date From"), + title=frappe._("Invalid Date Range") + ) \ No newline at end of file