summaryrefslogtreecommitdiff
path: root/archaeological_files/models.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2026-02-18 15:48:09 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2026-02-18 15:53:43 +0100
commit85f95a21983a5570381cd1a179669958dff30ba3 (patch)
tree472b25f61184666bc0be5e6a44eb550aabb66ba9 /archaeological_files/models.py
parent069b8b6a9097186826ea2a1fc2ac6f5d61b3d4be (diff)
downloadIshtar-85f95a21983a5570381cd1a179669958dff30ba3.tar.bz2
Ishtar-85f95a21983a5570381cd1a179669958dff30ba3.zip
✨ admin - price agreement: export all prices in a readable LO Calc document
Diffstat (limited to 'archaeological_files/models.py')
-rw-r--r--archaeological_files/models.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/archaeological_files/models.py b/archaeological_files/models.py
index 33af742ac..b41836f6a 100644
--- a/archaeological_files/models.py
+++ b/archaeological_files/models.py
@@ -20,6 +20,8 @@
import datetime
from collections import OrderedDict
import json
+import os
+import tempfile
from django.apps import apps
from django.conf import settings
@@ -30,6 +32,7 @@ from django.core.validators import MinValueValidator, MaxValueValidator
from django.db.models import Q, Max
from django.db.models.signals import post_save, m2m_changed, post_delete
from django.urls import reverse, reverse_lazy
+from django.utils.text import slugify
from ishtar_common.models_common import OrderedHierarchicalType
from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy, get_current_profile, \
@@ -74,6 +77,13 @@ from archaeological_operations.models import (
ParcelItem,
)
+UnoCalc = None
+if settings.USE_LIBREOFFICE:
+ try:
+ from ishtar_common.libreoffice import UnoCalc
+ except ImportError:
+ pass
+
class PriceAgreement(GeneralType):
order = models.IntegerField(_("Order"), default=10)
@@ -91,6 +101,98 @@ class PriceAgreement(GeneralType):
)
ADMIN_SECTION = _("Preventive")
+ def generate_summary_document(self, tmpdir=None):
+ if not UnoCalc:
+ return
+ uno = UnoCalc()
+ calc = uno.create_calc()
+ if not calc:
+ return
+ costs = {}
+ for cost in self.equipment_service_costs.filter(
+ parent__isnull=True).order_by("equipment_service_type__label", "id").all():
+ if cost.equipment_service_type.txt_idx not in costs:
+ costs[cost.equipment_service_type.txt_idx] = [cost.equipment_service_type]
+ costs[cost.equipment_service_type.txt_idx].append(cost)
+ for cost in self.equipment_service_costs.filter(
+ parent__isnull=False).order_by("equipment_service_type__label", "id").all():
+ if cost.parent.txt_idx not in costs:
+ costs[cost.parent.txt_idx] = [cost.equipment_service_type]
+ costs[cost.parent.txt_idx].append(cost)
+
+ lst = []
+ for type_slug in costs:
+ clst = []
+ for cost in costs[type_slug][1:]:
+ clst.append((
+ str(cost),
+ DCT_ES_UNITS[cost.unit] if cost.unit in DCT_ES_UNITS else "-",
+ cost.unitary_cost
+ ))
+ tpe = costs[type_slug][0]
+ lst.append([str(tpe), clst])
+
+ self._generate_page(
+ 0, _("Equipment - service costs"),
+ (_("Label"), _("Unit"), _("Price")),
+ lst, uno, calc)
+
+ lst = []
+ for job in self.jobs.order_by("order").all():
+ lst.append((
+ job.label,
+ _("Yes") if job.permanent_contract else _("No"),
+ job.ground_daily_cost,
+ job.daily_cost,
+ ))
+ header = [_("Label"), _("Permanent contract"),
+ _("Ground daily cost"), _("Daily cost")]
+ self._generate_page(1, _("Job cost"), header, lst, uno, calc, flat=True)
+
+ if not tmpdir:
+ tmpdir = tempfile.mkdtemp(prefix="ishtar-prices")
+ base = "{}-{}.ods".format(
+ _("ishtar-price-agreement"), slugify(self.label))
+ dest_filename = tmpdir + os.sep + base
+ uno.save_calc(calc, dest_filename)
+ return dest_filename
+
+ def __set_cost_cell(self, sheet, uno, line, cost):
+ for idx, c in enumerate(cost):
+ cell = sheet.getCellByPosition(idx, line)
+ if isinstance(c, (int, float)):
+ cell.setValue(c)
+ else:
+ cell.setString(str(c))
+ uno.format_cell_border(cell)
+
+ def _generate_page(self, page_number, name, header, costs_lst, uno, calc, flat=False):
+ sheet = uno.get_or_create_sheet(calc, page_number)
+ sheet.Name = str(name)
+ for col_number, column in enumerate(header):
+ # header
+ cell = sheet.getCellByPosition(col_number, 0)
+ cell.CharWeight = 150
+ cell.setString(str(column))
+ uno.format_cell_border(cell)
+
+ if flat:
+ line = 0
+ for cost in costs_lst:
+ line += 1
+ self.__set_cost_cell(sheet, uno, line, cost)
+ return
+ line = 1
+ for label, costs in costs_lst:
+ line += 1
+ cell = sheet.getCellByPosition(0, line)
+ cell.CharWeight = 150
+ cell.setString(label)
+ uno.format_cell_border(cell)
+ for cost in costs:
+ line += 1
+ self.__set_cost_cell(sheet, uno, line, cost)
+
class Job(GeneralType):
price_agreement = models.ForeignKey(