property tax report

This commit is contained in:
Ali 2025-11-20 15:33:08 +04:00
parent 4da6bf8bcf
commit 0ca228a6e7
4 changed files with 594 additions and 0 deletions

View File

@ -0,0 +1,377 @@
// Copyright (c) 2024, Your Company and contributors
// For license information, please see license.txt
frappe.query_reports["Property Tax Report"] = {
"filters": [
{
"fieldname": "company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company"),
"reqd": 1,
},
{
"fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"reqd": 0,
},
{
"fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.datetime.get_today(),
"reqd": 0,
}
],
"formatter": function (value, row, column, data, default_formatter) {
value = default_formatter(value, row, column, data);
// Подсветка колонок с суммами налоговых статей
if (column.fieldname && column.fieldname.startsWith("vm_")) {
if (value && parseFloat(value) > 0) {
let color = get_property_tax_color(column.fieldname);
let icon = get_property_tax_icon(column.fieldname);
value = `<span style="color: ${color}; font-weight: bold; background-color: ${color}15; padding: 2px 6px; border-radius: 3px; border-left: 2px solid ${color};">${icon} ${value}</span>`;
} else if (value == 0 || !value) {
value = `<span style="color: #ccc;">0.00</span>`;
}
}
// Подсветка Asset колонки
if (column.fieldname == "asset" && value) {
value = `<span style="color: #495057; font-weight: bold;">🏢 ${value}</span>`;
}
// Подсветка Asset Name колонки
if (column.fieldname == "asset_name" && value) {
value = `<span style="color: #6c757d; font-weight: 500;">📝 ${value}</span>`;
}
return value;
},
"onload": function(report) {
// Добавляем кастомные кнопки
report.page.add_inner_button(__("Export Property Tax Summary"), function() {
export_property_tax_summary(report);
});
report.page.add_inner_button(__("Show Article Categories"), function() {
show_property_tax_categories();
});
// Добавляем информационное сообщение
report.page.add_inner_button(__("About Property Tax"), function() {
show_property_tax_info();
});
},
"after_datatable_render": function(datatable_obj) {
// Добавляем итоговую статистику
setTimeout(() => {
add_property_tax_statistics(datatable_obj);
}, 500);
}
};
// Функция определения цвета для налоговой статьи
function get_property_tax_color(fieldname) {
if (fieldname.includes("207_3") || fieldname.includes("207_4")) {
// Промышленные парки (синяя гамма)
return "#0d6efd";
} else if (fieldname.includes("207_5") || fieldname.includes("207_6")) {
// Инвестиции и КОБ (зеленая гамма)
return "#198754";
} else if (fieldname.includes("207_7")) {
// Кредитные организации (фиолетовая гамма)
return "#6610f2";
} else if (fieldname.includes("207_8")) {
// Геологические работы (оранжевая гамма)
return "#fd7e14";
} else if (fieldname.includes("207_9") || fieldname.includes("207_12")) {
// Кредиторы (розовая гамма)
return "#d63384";
} else if (fieldname.includes("207_10")) {
// Импортные товары (голубая гамма)
return "#0dcaf0";
} else if (fieldname.includes("207_11")) {
// Приватизация (индиго гамма)
return "#6f42c1";
} else if (fieldname.includes("227_1")) {
// Земельный налог (зеленая гамма)
return "#20c997";
} else {
// Остальные статьи (серая гамма)
return "#6c757d";
}
}
// Функция определения иконки для налоговой статьи
function get_property_tax_icon(fieldname) {
if (fieldname.includes("207_3") || fieldname.includes("207_4")) {
return "🏭"; // Промышленные парки
} else if (fieldname.includes("207_5") || fieldname.includes("207_6")) {
return "💼"; // Инвестиции и КОБ
} else if (fieldname.includes("207_7")) {
return "🏦"; // Кредитные организации
} else if (fieldname.includes("207_8")) {
return "⛏️"; // Геологические работы
} else if (fieldname.includes("207_9") || fieldname.includes("207_12")) {
return "💳"; // Кредиторы
} else if (fieldname.includes("207_10")) {
return "📦"; // Импортные товары
} else if (fieldname.includes("207_11")) {
return "🏛️"; // Приватизация
} else if (fieldname.includes("227_1")) {
return "🌾"; // Земельный налог
} else {
return "📋"; // Остальные
}
}
// Функция показа информации о налоговых статьях
function show_property_tax_info() {
let info_html = '<div class="property-tax-info">';
info_html += '<h4 style="color: #495057; margin-bottom: 15px;">📋 Əmlak Vergisi Maddələri</h4>';
info_html += '<div class="row">';
info_html += '<div class="col-md-6">';
info_html += '<h5 style="color: #0d6efd; margin-bottom: 10px;">🏭 207.3-207.4 Maddələri (Sənaye Parkları)</h5>';
info_html += '<ul style="font-size: 12px; color: #6c757d;">';
info_html += '<li>207.3 - Sənaye parkı rezidenti</li>';
info_html += '<li>207.4 - İdarəedici təşkilat</li>';
info_html += '</ul>';
info_html += '</div>';
info_html += '<div class="col-md-6">';
info_html += '<h5 style="color: #198754; margin-bottom: 10px;">💼 207.5-207.6 Maddələri (İnvestisiya)</h5>';
info_html += '<ul style="font-size: 12px; color: #6c757d;">';
info_html += '<li>207.5 - İnvestisiya təşviqi sənədi</li>';
info_html += '<li>207.6 - KOB klaster şirkətləri</li>';
info_html += '</ul>';
info_html += '</div>';
info_html += '</div>';
info_html += '<div class="row">';
info_html += '<div class="col-md-6">';
info_html += '<h5 style="color: #6610f2; margin-bottom: 10px;">🏦 207.7-207.9 Maddələri (Maliyyə)</h5>';
info_html += '<ul style="font-size: 12px; color: #6c757d;">';
info_html += '<li>207.7 - Aqrarkredit və Sənaye Korporasiyası</li>';
info_html += '<li>207.9 - Kredit təşkilatları</li>';
info_html += '</ul>';
info_html += '</div>';
info_html += '<div class="col-md-6">';
info_html += '<h5 style="color: #fd7e14; margin-bottom: 10px;">⛏️ 207.8-207.11 Maddələri (Xüsusi)</h5>';
info_html += '<ul style="font-size: 12px; color: #6c757d;">';
info_html += '<li>207.8 - Geoloji kəşfiyyat</li>';
info_html += '<li>207.10 - İdxal malları</li>';
info_html += '<li>207.11 - Özəlləşdirilmiş əsas vəsaitlər</li>';
info_html += '</ul>';
info_html += '</div>';
info_html += '</div>';
info_html += '<hr>';
info_html += '<p style="color: #6c757d; font-size: 13px; text-align: center;">';
info_html += 'Bu hesabat Asset-lərdə tax_article sahəsinə əsasən əmlak vergisini bölüşdürür';
info_html += '</p>';
info_html += '</div>';
frappe.msgprint({
title: __("Property Tax Information"),
message: info_html,
wide: true
});
}
// Функция показа категорий налоговых статей
function show_property_tax_categories() {
let categories_html = '<div class="property-tax-categories">';
categories_html += '<h4>🎯 Əmlak Vergisi Kateqoriyaları:</h4>';
categories_html += '<div class="row">';
const categories = [
{name: "🏭 Sənaye Parkları", color: "#0d6efd", articles: ["207.3", "207.4"]},
{name: "💼 İnvestisiya və KOB", color: "#198754", articles: ["207.5", "207.6"]},
{name: "🏦 Maliyyə Təşkilatları", color: "#6610f2", articles: ["207.7", "207.9", "207.12"]},
{name: "⛏️ Geoloji İşlər", color: "#fd7e14", articles: ["207.8"]},
{name: "📦 İdxal Malları", color: "#0dcaf0", articles: ["207.10"]},
{name: "🏛️ Özəlləşdirmə", color: "#6f42c1", articles: ["207.11"]},
{name: "🌾 Torpaq Vergisi", color: "#20c997", articles: ["227.1"]}
];
categories.forEach((category, index) => {
if (index % 2 === 0 && index > 0) {
categories_html += '</div><div class="row">';
}
categories_html += '<div class="col-md-6" style="margin-bottom: 15px;">';
categories_html += `<div style="padding: 15px; border: 2px solid ${category.color}; border-radius: 8px; background: ${category.color}10;">`;
categories_html += `<h5 style="color: ${category.color};">${category.name}</h5>`;
categories_html += '<div style="font-size: 12px; color: #6c757d;">';
category.articles.forEach(article => {
categories_html += `<span style="margin-right: 8px; background: white; padding: 2px 6px; border-radius: 3px; border: 1px solid ${category.color};">VM ${article}</span>`;
});
categories_html += '</div>';
categories_html += '</div>';
categories_html += '</div>';
});
categories_html += '</div>';
categories_html += '</div>';
frappe.msgprint({
title: __("Article Categories"),
message: categories_html,
wide: true
});
}
// Функция экспорта сводки по налоговым статьям
function export_property_tax_summary(report) {
let data = report.data;
let summary = calculate_property_tax_totals(data);
// Создаем CSV с итогами
let csv_content = "Tax Article,Total Asset Cost,Assets Count\n";
summary.forEach(item => {
if (item.total > 0) {
csv_content += `"${item.article}",${item.total},${item.count}\n`;
}
});
// Добавляем общие итоги
let grand_total = summary.reduce((acc, item) => acc + item.total, 0);
let total_assets = data.length;
csv_content += `\n"CƏMİ","${grand_total}","${total_assets}"\n`;
// Скачиваем файл
let blob = new Blob([csv_content], { type: 'text/csv;charset=utf-8' });
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = 'property_tax_summary_' + frappe.datetime.get_today() + '.csv';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
frappe.show_alert({message: __("Property tax summary exported successfully"), indicator: "green"});
}
// Функция расчета итогов по налоговым статьям
function calculate_property_tax_totals(data) {
let summary = [];
let article_totals = {};
// Получаем все возможные статьи из колонок
data.forEach(row => {
Object.keys(row).forEach(key => {
if (key.startsWith('vm_') && row[key] > 0) {
if (!article_totals[key]) {
article_totals[key] = {total: 0, count: 0};
}
article_totals[key].total += row[key];
article_totals[key].count++;
}
});
});
// Конвертируем в массив
Object.keys(article_totals).forEach(key => {
summary.push({
article: convert_field_key_to_display_name(key),
total: article_totals[key].total,
count: article_totals[key].count
});
});
// Сортируем по общей сумме
summary.sort((a, b) => b.total - a.total);
return summary;
}
// Функция конвертации ключа поля в отображаемое название
function convert_field_key_to_display_name(fieldKey) {
const mapping = {
'vm_207_3': 'VM 207.3',
'vm_207_4': 'VM 207.4',
'vm_207_5': 'VM 207.5',
'vm_207_6': 'VM 207.6',
'vm_207_7': 'VM 207.7',
'vm_207_8': 'VM 207.8',
'vm_207_9': 'VM 207.9',
'vm_207_10': 'VM 207.10',
'vm_207_11': 'VM 207.11',
'vm_207_12': 'VM 207.12',
'vm_227_1': 'VM 227.1'
};
return mapping[fieldKey] || fieldKey.replace(/_/g, '.').replace('vm.', 'VM ');
}
// Функция добавления статистики под таблицу
function add_property_tax_statistics(datatable_obj) {
if (datatable_obj && datatable_obj.data) {
let summary = calculate_property_tax_totals(datatable_obj.data);
let topArticles = summary.slice(0, 10); // Топ 10 статей
let stats_html = '<div class="property-tax-statistics" style="margin-top: 20px; padding: 20px; background: linear-gradient(135deg, #f8f9ff 0%, #fff 100%); border-radius: 8px; border: 2px solid #6610f2; box-shadow: 0 2px 8px rgba(102,16,242,0.1);">';
stats_html += '<h4 style="margin-bottom: 15px; color: #6610f2; display: flex; align-items: center;"><span style="margin-right: 8px;">📊</span> Əmlak Vergisi Statistikası:</h4>';
// Топ статьи
if (topArticles.length > 0) {
stats_html += '<h5 style="color: #495057; margin-bottom: 15px;">🏆 Ən Yüksək Məbləğli Maddələr:</h5>';
stats_html += '<div class="row">';
topArticles.slice(0, 6).forEach((article, index) => {
if (index % 3 === 0 && index > 0) {
stats_html += '</div><div class="row">';
}
let color = get_property_tax_color(Object.keys(datatable_obj.data[0]).find(k => convert_field_key_to_display_name(k) === article.article) || 'vm_other');
stats_html += '<div class="col-md-4" style="margin-bottom: 10px;">';
stats_html += `<div style="padding: 10px; border: 2px solid ${color}; border-radius: 6px; background: white; text-align: center;">`;
stats_html += `<strong style="color: ${color}; font-size: 12px;">${article.article}</strong><br>`;
stats_html += `<span style="font-size: 16px; font-weight: bold; color: ${color};">${article.total.toFixed(2)}</span><br>`;
stats_html += `<small style="color: #6c757d;">${article.count} əmlak</small>`;
stats_html += '</div>';
stats_html += '</div>';
});
stats_html += '</div>';
}
// Общие итоги
let grand_total = summary.reduce((acc, item) => acc + item.total, 0);
let total_articles = summary.length;
let total_assets = datatable_obj.data.length;
stats_html += '<div style="margin-top: 20px; padding: 15px; border-top: 3px solid #6610f2; background: linear-gradient(135deg, #6610f210 0%, #fff 100%);">';
stats_html += '<div class="row text-center">';
stats_html += `<div class="col-md-3"><span style="color: #6610f2; font-size: 14px; font-weight: bold;">📋 Aktiv Maddələr<br><span style="font-size: 18px;">${total_articles}</span></span></div>`;
stats_html += `<div class="col-md-3"><span style="color: #198754; font-size: 14px; font-weight: bold;">💰 Ümumi Məbləğ<br><span style="font-size: 18px;">${grand_total.toFixed(2)}</span></span></div>`;
stats_html += `<div class="col-md-3"><span style="color: #fd7e14; font-size: 14px; font-weight: bold;">🏢 Cəmi Əmlak<br><span style="font-size: 18px;">${total_assets}</span></span></div>`;
stats_html += `<div class="col-md-3"><span style="color: #d63384; font-size: 14px; font-weight: bold;">📈 Orta Məbləğ<br><span style="font-size: 18px;">${total_assets > 0 ? (grand_total / total_assets).toFixed(2) : '0.00'}</span></span></div>`;
stats_html += '</div>';
stats_html += '</div>';
stats_html += '</div>';
// Удаляем предыдущую статистику если есть
$('.property-tax-statistics').remove();
// Добавляем новую статистику
$(stats_html).insertAfter('.datatable');
}
}

View File

@ -0,0 +1,31 @@
{
"add_total_row": 0,
"add_translate_data": 0,
"columns": [],
"creation": "2025-11-20 15:07:06.112661",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"letterhead": null,
"modified": "2025-11-20 15:07:22.265683",
"modified_by": "Administrator",
"module": "Taxes Az",
"name": "Property Tax Report",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Asset",
"report_name": "Property Tax Report",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts User"
},
{
"role": "Quality Manager"
}
],
"timeout": 0
}

View File

@ -0,0 +1,186 @@
# Copyright (c) 2024, Your Company and contributors
# For license information, please see license.txt
import frappe
from frappe import _
from frappe.utils import flt
def execute(filters=None):
columns, data = get_columns(), get_data(filters)
return columns, data
def get_data(filters):
"""Получаем данные по Asset с распределением по налоговым статьям"""
# Получаем Assets с учетом фильтров
assets = get_assets(filters)
if not assets:
return []
# Получаем маппинг name -> article_name из Tax Article
tax_article_names_mapping = get_tax_article_names_mapping()
# Получаем маппинг полных названий к ключам полей
tax_articles_mapping = get_tax_articles_mapping()
# Формируем данные
data = []
for asset in assets:
row = {
'asset': asset['name'],
'asset_name': asset['asset_name'],
'company': asset['company']
}
# Инициализируем все колонки нулями
for field_key in tax_articles_mapping.values():
row[field_key] = 0
# Проверяем agricultural_tax_article
if asset.get('agricultural_tax_article'):
tax_article_name = asset['agricultural_tax_article']
if tax_article_name in tax_article_names_mapping:
full_article_name = tax_article_names_mapping[tax_article_name]
if full_article_name in tax_articles_mapping:
field_key = tax_articles_mapping[full_article_name]
row[field_key] = flt(asset['total_asset_cost'])
# Проверяем industrial_tax_article
elif asset.get('industrial_tax_article'):
tax_article_name = asset['industrial_tax_article']
if tax_article_name in tax_article_names_mapping:
full_article_name = tax_article_names_mapping[tax_article_name]
if full_article_name in tax_articles_mapping:
field_key = tax_articles_mapping[full_article_name]
row[field_key] = flt(asset['total_asset_cost'])
# Добавляем строку только если есть tax_article
if asset.get('agricultural_tax_article') or asset.get('industrial_tax_article'):
data.append(row)
return data
def get_tax_article_names_mapping():
"""Получает маппинг name -> article_name из таблицы Tax Article"""
tax_articles = frappe.db.sql("""
SELECT name, article_name
FROM `tabTax Article`
WHERE article_name IS NOT NULL AND article_name != ''
""", as_dict=True)
return {article['name']: article['article_name'] for article in tax_articles}
def get_assets(filters):
"""Получает Assets с учетом фильтров"""
conditions = []
values = []
# Фильтр по компании
if filters.get("company"):
conditions.append("company = %s")
values.append(filters.get("company"))
# Только submitted статус
conditions.append("status = 'Submitted'")
# Только assets с заполненным tax_article
conditions.append("(agricultural_tax_article IS NOT NULL AND agricultural_tax_article != '' OR industrial_tax_article IS NOT NULL AND industrial_tax_article != '')")
where_clause = ""
if conditions:
where_clause = "WHERE " + " AND ".join(conditions)
query = f"""
SELECT
name,
asset_name,
company,
agricultural_tax_article,
industrial_tax_article,
total_asset_cost
FROM
`tabAsset`
{where_clause}
ORDER BY
name
"""
return frappe.db.sql(query, values, as_dict=True)
def get_tax_articles_mapping():
"""Маппинг налоговых статей для Property Tax к полям"""
return {
"Vergi Məcəlləsinin 207.3-cü maddəsinə əsasən Sənaye, yaxud texnologiyalar parklarının rezidenti olan hüquqi şəxsin sənaye, yaxud texnologiyalar parklarında istifadə etdikləri torpaqlara görə": "vm_207_3",
"Vergi Məcəlləsinin 207.4-cü maddəsinə əsasən Sənaye, yaxud texnologiyalar parklarının idarəedici təşkilatı və ya operatorunun sənaye, yaxud texnologiyalar parklarının ərazisində istifadə etdiyi torpaqlara görə": "vm_207_4",
"Vergi Məcəlləsinin 207.5-ci maddəsinə əsasən İnvestisiya təşviqi sənədini almış hüquqi şəxs həmin sənədi aldığı tarixdən mülkiyyətində və ya istifadəsində olan müvafiq torpaqlara görə": "vm_207_5",
"Vergi Məcəlləsinin 207.6-cı maddəsinə əsasən KOB klaster şirkətləri KOB klaster şirkətlərinin reyestrinə daxil edildiyi tarixdən 7 il müddətinə mülkiyyətində və ya istifadəsində olan torpaqlara görə": "vm_207_6",
"Vergi Məcəlləsinin 207.7-ci maddəsinə əsasən \"Aqrarkredit\" Qapalı Səhmdar Cəmiyyəti Bank Olmayan Kredit Təşkilatı\"Azərbaycan Sənaye Korporasiyası\"ıq Səhmdar Cəmiyyəti ödəmə qabiliyyətini itirmiş bankların rezolyusiyası və sağlamlaşdırma tədbirləri çərçivəsində Azərbaycan Respublikasının Prezidentinin qərarına əsasən aldığı problemli aktivlərin (borcların) əvəzində əldə etdiyi, onun mülkiyyətində (balansında) olan və siyahısını Azərbaycan Respublikasının İqtisadiyyat Nazirliyi ilə razılaşdırdığı torpağa görə": "vm_207_7",
"Vergi Məcəlləsinin 207.8-ci maddəsinə əsasən Geoloji ayırma sənədi əsasında faydalı qazıntı yataqlarının (neft və qaz yataqları istisna olmaqla) axtarışı, qiymətləndirilməsi və kəşfiyyatı işlərinə cəlb edilən torpaq sahələrinə görə torpaq vergisi müvafiq təsdiqedici sənədlər (geoloji-kəşfiyyat işlərini həyata keçirən şəxsin podrat müqaviləsi, geoloji-kəşfiyyat planı, geoloji-kəşfiyyatla bağlı təqdim edilən hesabat) əsasında faydalı qazıntı yataqlarının axtarışı, qiymətləndirilməsi və kəşfiyyatı işlərinə başlanıldığı təqvim ili üzrə 75 faiz": "vm_207_8",
"Vergi Məcəlləsinin 207.9-cu maddəsinə əsasən Vergi Məcəlləsinin 207.9-cu maddəsinə əsasən Kredit təşkilatları məhkəmənin qanuni qüvvəyə minmiş qərarına əsasən müflis elan olunduğu halda kredit təşkilatının müflis elan olunması ilə bağlı məhkəmə qərarının qüvvəyə mindiyi ildən etibarən torpaq vergisini ödəməkdən azaddırlar": "vm_207_9",
"Vergi Məcəlləsinin 207.10-cu maddəsinə əsasən Siyahısı Azərbaycan Respublikasının Nazirlər Kabineti tərəfindən təsdiq edilmiş idxal mallarını yerli istehsal (emal) malları ilə əvəz edəcək qida (ərzaq) məhsullarının istehsalı ilə məşğul olan hüquqi və fiziki şəxslər həmin fəaliyyət prosesində istifadə olunan torpaqlara görə müvafiq siyahının təsdiq edildiyi ildən etibarən 7 il müddətinə torpaq vergisini ödəməkdən azaddırlar": "vm_207_10",
"Vergi Məcəlləsinin 207.11-ci maddəsinə əsasən Azərbaycan Respublikasında dövlət əmlakının özəlləşdirilməsinin dövlət proqramlarına uyğun olaraq 2023-cü il 1 yanvar tarixindən sonra özəlləşdirilməsi barədə qərar qəbul edilən dövlətə məxsus hüquqi şəxslər özəlləşdirilməsi barədə qərarın qəbul edildiyi ildən etibarən özəlləşdirilmə prosesi müddətində, lakin 3 ildən çox olmayaraq, torpaq vergisini ödəməkdən azaddırlar": "vm_207_11",
"Vergi məcəlləsinin 207.12-ci maddəsinə əsasən Kredit təşkilatları verilmiş kredit müqabilində onların mülkiyyətinə keçən torpaqlara görə": "vm_207_12",
"Vergi Məcəlləsinin 227.1-ci maddəsinə əsasən": "vm_227_1"
}
def get_field_to_label_mapping():
"""Маппинг ключей полей к коротким названиям колонок"""
return {
"vm_207_3": "VM 207.3",
"vm_207_4": "VM 207.4",
"vm_207_5": "VM 207.5",
"vm_207_6": "VM 207.6",
"vm_207_7": "VM 207.7",
"vm_207_8": "VM 207.8",
"vm_207_9": "VM 207.9",
"vm_207_10": "VM 207.10",
"vm_207_11": "VM 207.11",
"vm_207_12": "VM 207.12",
"vm_227_1": "VM 227.1"
}
def get_columns():
"""Создает колонки отчета"""
columns = []
# Основные колонки
columns.extend([
{
"label": "Asset",
"fieldname": "asset",
"fieldtype": "Link",
"options": "Asset",
"width": 150
},
{
"label": "Asset Name",
"fieldname": "asset_name",
"fieldtype": "Data",
"width": 200
}
])
# Получаем маппинг полей к названиям
field_to_label = get_field_to_label_mapping()
# Создаем колонки для каждого поля в правильном порядке
for field_key in sorted(field_to_label.keys()):
label = field_to_label[field_key]
columns.append({
"label": label,
"fieldname": field_key,
"fieldtype": "Currency",
"width": 120
})
return columns