From 5cb168407c8fa19ff13e148ce1536ab0251c956a Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 5 Jul 2023 17:56:38 +0530 Subject: [PATCH 1/9] perf: Cache Water Body Data to make API Performant - On insert, update and deletion rebuild water body cache - Cache all water bodies and also cache fishing area wise - Return cached data if available via public API --- landa/api.py | 70 +++++----------- .../doctype/water_body/water_body.py | 80 ++++++++++++++++++- 2 files changed, 99 insertions(+), 51 deletions(-) diff --git a/landa/api.py b/landa/api.py index b03d7b28..686919eb 100644 --- a/landa/api.py +++ b/landa/api.py @@ -3,6 +3,11 @@ import frappe +from landa.water_body_management.doctype.water_body.water_body import ( + build_water_body_cache, + build_water_body_data, +) + @frappe.whitelist(allow_guest=True, methods=["GET"]) def organization(id: str = None) -> List[Dict]: @@ -71,56 +76,21 @@ def organization(id: str = None) -> List[Dict]: @frappe.whitelist(allow_guest=True, methods=["GET"]) def water_body(id: str = None, fishing_area: str = None) -> List[Dict]: """Return a list of water bodies with fish species and special provisions.""" - filters = [ - ["Water Body", "is_active", "=", 1], - ["Water Body", "display_in_fishing_guide", "=", 1], - ] - if id and isinstance(id, str): - filters.append(["Water Body", "name", "=", id]) + if id: + # We do not cache ID since it's uniqueness makes the API performant + return build_water_body_data(id, fishing_area) - if fishing_area and isinstance(fishing_area, str): - filters.append(["Water Body", "fishing_area", "=", fishing_area]) + key = fishing_area or "all" + cache_exists = frappe.cache().hexists("water_body_data", key) + + if not cache_exists: + # Build the cache (for future calls) + build_water_body_cache(fishing_area) + + # return the cached result + return get_water_body_cache(key) - water_bodies = frappe.get_all( - "Water Body", - filters=filters, - fields=[ - "name as id", - "title", - "fishing_area", - "fishing_area_name", - "organization", - "organization_name", - "has_master_key_system", - "guest_passes_available", - "general_public_information", - "current_public_information", - "water_body_size as size", - "water_body_size_unit as size_unit", - "location", - ], - ) - for water_body in water_bodies: - water_body["fish_species"] = frappe.get_all( - "Fish Species Table", - filters={"parent": water_body["id"]}, - pluck="fish_species", - ) - - water_body["special_provisions"] = frappe.get_all( - "Water Body Special Provision Table", - filters={"parent": water_body["id"]}, - fields=["water_body_special_provision as id", "short_code"], - ) - - water_body["organizations"] = frappe.get_all( - "Water Body Management Local Organization", - filters={"water_body": water_body["id"]}, - fields=["organization as id", "organization_name"], - ) - - if water_body.location: - water_body["geojson"] = json.loads(water_body.location) - - return water_bodies +def get_water_body_cache(key: str) -> List[Dict]: + """Return a **CACHED** list of water bodies with fish species and special provisions.""" + return frappe.cache().hget("water_body_data", key) diff --git a/landa/water_body_management/doctype/water_body/water_body.py b/landa/water_body_management/doctype/water_body/water_body.py index dbb9b1b5..ebc413e5 100644 --- a/landa/water_body_management/doctype/water_body/water_body.py +++ b/landa/water_body_management/doctype/water_body/water_body.py @@ -1,6 +1,6 @@ # Copyright (c) 2021, Real Experts GmbH and contributors # For license information, please see license.txt - +from typing import Dict, List import frappe from frappe import _ @@ -11,6 +11,12 @@ class WaterBody(Document): + def on_update(self): + self.rebuild_water_body_cache() + + def on_trash(self): + self.rebuild_water_body_cache() + def validate(self): self.validate_edit_access() self.validate_blacklisted_fish_species() @@ -35,6 +41,15 @@ def validate_blacklisted_fish_species(self): title=_("Invalid Species"), ) + def rebuild_water_body_cache(self): + # Invalidate Cache + frappe.cache().hdel("water_body_data", "all") + frappe.cache().hdel("water_body_data", self.fishing_area) + + # Build Cache for all water bodies and fishing area wise + build_water_body_cache() + build_water_body_cache(fishing_area=self.fishing_area) + def remove_outdated_information(): for name in frappe.get_all( @@ -49,3 +64,66 @@ def remove_outdated_information(): water_body.current_public_information = None water_body.current_information_expires_on = None water_body.save() + + +def build_water_body_cache(fishing_area: str = None): + """Build the water body cache for all water bodies **OR** fishing area wise.""" + water_bodies = build_water_body_data(fishing_area=fishing_area) + frappe.cache().hset("water_body_data", fishing_area, water_bodies) + + +def build_water_body_data(id: str = None, fishing_area: str = None) -> List[Dict]: + """Return a list of water bodies with fish species and special provisions.""" + filters = [ + ["Water Body", "is_active", "=", 1], + ["Water Body", "display_in_fishing_guide", "=", 1], + ] + if id and isinstance(id, str): + filters.append(["Water Body", "name", "=", id]) + + if fishing_area and isinstance(fishing_area, str): + filters.append(["Water Body", "fishing_area", "=", fishing_area]) + + water_bodies = frappe.get_all( + "Water Body", + filters=filters, + fields=[ + "name as id", + "title", + "fishing_area", + "fishing_area_name", + "organization", + "organization_name", + "has_master_key_system", + "guest_passes_available", + "general_public_information", + "current_public_information", + "water_body_size as size", + "water_body_size_unit as size_unit", + "location", + ], + ) + + for water_body in water_bodies: + water_body["fish_species"] = frappe.get_all( + "Fish Species Table", + filters={"parent": water_body["id"]}, + pluck="fish_species", + ) + + water_body["special_provisions"] = frappe.get_all( + "Water Body Special Provision Table", + filters={"parent": water_body["id"]}, + fields=["water_body_special_provision as id", "short_code"], + ) + + water_body["organizations"] = frappe.get_all( + "Water Body Management Local Organization", + filters={"water_body": water_body["id"]}, + fields=["organization as id", "organization_name"], + ) + + if water_body.location: + water_body["geojson"] = frappe.parse_json(water_body.location) + + return water_bodies From e309528a9739f5bec628c05af8bbd1d77cef9acd Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 10 Jul 2023 21:26:17 +0530 Subject: [PATCH 2/9] perf: Water Body cache generation - Use multi join sql query so that it is just one db query - Loop over this data to create a flat water body wise map with child data --- .../doctype/water_body/water_body.py | 173 +++++++++++++----- 1 file changed, 127 insertions(+), 46 deletions(-) diff --git a/landa/water_body_management/doctype/water_body/water_body.py b/landa/water_body_management/doctype/water_body/water_body.py index ebc413e5..6d787239 100644 --- a/landa/water_body_management/doctype/water_body/water_body.py +++ b/landa/water_body_management/doctype/water_body/water_body.py @@ -1,5 +1,6 @@ # Copyright (c) 2021, Real Experts GmbH and contributors # For license information, please see license.txt +from collections import defaultdict from typing import Dict, List import frappe @@ -67,63 +68,143 @@ def remove_outdated_information(): def build_water_body_cache(fishing_area: str = None): - """Build the water body cache for all water bodies **OR** fishing area wise.""" + """ + Build the water body cache for all water bodies **OR** fishing area wise. + """ water_bodies = build_water_body_data(fishing_area=fishing_area) - frappe.cache().hset("water_body_data", fishing_area, water_bodies) + key = fishing_area or "all" + frappe.cache().hset("water_body_data", key, water_bodies) def build_water_body_data(id: str = None, fishing_area: str = None) -> List[Dict]: - """Return a list of water bodies with fish species and special provisions.""" - filters = [ - ["Water Body", "is_active", "=", 1], - ["Water Body", "display_in_fishing_guide", "=", 1], - ] + """ + Return a list of water bodies with fish species and special provisions + """ + result = query_water_body_data(id=id, fishing_area=fishing_area) + return consolidate_water_body_data(water_body_data=result) + + +def query_water_body_data(id: str = None, fishing_area: str = None) -> List[Dict]: + water_body = frappe.qb.DocType("Water Body") + fish_species_table = frappe.qb.DocType("Fish Species Table") + wb_provision_table = frappe.qb.DocType("Water Body Special Provision Table") + wb_local_org_table = frappe.qb.DocType("Water Body Management Local Organization") + + query = ( + frappe.qb.from_(water_body) + .left_join(fish_species_table) + .on(fish_species_table.parent == water_body.name) + .left_join(wb_provision_table) + .on(wb_provision_table.parent == water_body.name) + .left_join(wb_local_org_table) + .on(wb_local_org_table.water_body == water_body.name) + .select( + water_body.name.as_("id"), + water_body.title, + water_body.fishing_area, + water_body.fishing_area_name, + water_body.organization, + water_body.organization_name, + water_body.has_master_key_system, + water_body.guest_passes_available, + water_body.general_public_information, + water_body.current_public_information, + water_body.water_body_size.as_("size"), + water_body.water_body_size_unit.as_("size_unit"), + water_body.location, + fish_species_table.fish_species, + wb_provision_table.water_body_special_provision, + wb_provision_table.short_code, + wb_local_org_table.organization.as_("local_organization"), + wb_local_org_table.organization_name.as_("local_organization_name"), + ) + .where(water_body.is_active == 1) + .where(water_body.display_in_fishing_guide == 1) + ) + if id and isinstance(id, str): - filters.append(["Water Body", "name", "=", id]) + query = query.where(water_body.name == id) if fishing_area and isinstance(fishing_area, str): - filters.append(["Water Body", "fishing_area", "=", fishing_area]) + query = query.where(water_body.fishing_area == fishing_area) - water_bodies = frappe.get_all( - "Water Body", - filters=filters, - fields=[ - "name as id", - "title", - "fishing_area", - "fishing_area_name", - "organization", - "organization_name", - "has_master_key_system", - "guest_passes_available", - "general_public_information", - "current_public_information", - "water_body_size as size", - "water_body_size_unit as size_unit", - "location", - ], + return query.run(as_dict=True) + + +def consolidate_water_body_data(water_body_data: List[Dict]) -> List[Dict]: + """ + Deduplicate the water body data such that each water body has a list of unique + fish species, special provisions and local organizations. + """ + water_body_map = {} # {water_body_name: water_body_data} + fish_species_map, provision_map, local_org_map = ( + defaultdict(list), + defaultdict(list), + defaultdict(list), ) - for water_body in water_bodies: - water_body["fish_species"] = frappe.get_all( - "Fish Species Table", - filters={"parent": water_body["id"]}, - pluck="fish_species", - ) + for entry in water_body_data: + water_body_name = entry.get("id") + if not water_body_name in water_body_map: + # Add entry to map if it does not exist + water_body_map[water_body_name] = init_row(water_body_row=entry) - water_body["special_provisions"] = frappe.get_all( - "Water Body Special Provision Table", - filters={"parent": water_body["id"]}, - fields=["water_body_special_provision as id", "short_code"], - ) + result_entry = water_body_map[water_body_name] - water_body["organizations"] = frappe.get_all( - "Water Body Management Local Organization", - filters={"water_body": water_body["id"]}, - fields=["organization as id", "organization_name"], - ) + # Add unique child table and Water Body Management Local Organization data + fish_species = entry.get("fish_species") + add_to_map(fish_species, "fish_species", entry, fish_species_map, result_entry) + + provision = entry.get("water_body_special_provision") + add_to_map(provision, "special_provisions", entry, provision_map, result_entry) + + org = entry.get("local_organization") + add_to_map(org, "organizations", entry, local_org_map, result_entry) - if water_body.location: - water_body["geojson"] = frappe.parse_json(water_body.location) + return [water_body_map.get(key) for key in water_body_map] - return water_bodies + +def init_row(water_body_row: Dict) -> Dict: + # Prepare row to have Water Body data (excluding child tables) + water_body_copy = water_body_row.copy() + + if water_body_copy.location: + water_body_copy["geojson"] = frappe.parse_json(water_body_copy.location) + + for field in ( + "fish_species", + "water_body_special_provision", + "short_code", + "local_organization", + "local_organization_name", + ): + water_body_copy.pop(field) # Remove child table fields + + for field in ("fish_species", "special_provisions", "organizations"): + # Re-insert child table fields as lists + water_body_copy[field] = [] + + return water_body_copy + + +def add_to_map(value, field, water_body, checking_map, result_map): + """ + Add the value to the `result_map` if it does not exist in the `checking_map`. + Also update the `checking_map` with the value. + """ + water_body_name = water_body.get("id") + checking_result_map = checking_map[water_body_name] + + if not value or (value in checking_result_map): + return + + checking_result_map.append(value) + + if field == "fish_species": + result_map[field].append(value) + elif field == "special_provisions": + result_map[field].append({"id": value, "short_code": water_body.get("short_code")}) + else: + result_map[field].append( + {"id": value, "organization_name": water_body.get("local_organization_name")} + ) From 52db4ebc46d4efce8d890289ad59a1fb685fb6ee Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 10 Jul 2023 21:59:22 +0530 Subject: [PATCH 3/9] chore: Build cache on migrate and on WBMLO update --- landa/patches.txt | 1 + landa/patches/build_water_body_cache.py | 11 ++++++++++ .../doctype/water_body/water_body.py | 22 +++++++++++-------- ...ater_body_management_local_organization.py | 8 ++++++- 4 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 landa/patches/build_water_body_cache.py diff --git a/landa/patches.txt b/landa/patches.txt index 96ae801f..43e00a99 100644 --- a/landa/patches.txt +++ b/landa/patches.txt @@ -23,3 +23,4 @@ landa.patches.set_billing_and_shipping_defaults landa.patches.delete_old_scheduled_job_logs landa.patches.update_system_settings landa.patches.delete_customized_workspaces # 2023-06-06 +landa.patches.build_water_body_cache diff --git a/landa/patches/build_water_body_cache.py b/landa/patches/build_water_body_cache.py new file mode 100644 index 00000000..11b132e1 --- /dev/null +++ b/landa/patches/build_water_body_cache.py @@ -0,0 +1,11 @@ +import frappe + +from landa.water_body_management.doctype.water_body.water_body import build_water_body_cache + + +def execute(): + build_water_body_cache() # Cache all Water Bodies + + fishing_areas = frappe.get_all("Fishing Area", pluck="name") + for area in fishing_areas: + build_water_body_cache(fishing_area=area) # Cache Fishing Area wise diff --git a/landa/water_body_management/doctype/water_body/water_body.py b/landa/water_body_management/doctype/water_body/water_body.py index 6d787239..b9463a0c 100644 --- a/landa/water_body_management/doctype/water_body/water_body.py +++ b/landa/water_body_management/doctype/water_body/water_body.py @@ -13,10 +13,10 @@ class WaterBody(Document): def on_update(self): - self.rebuild_water_body_cache() + rebuild_water_body_cache(self.fishing_area) def on_trash(self): - self.rebuild_water_body_cache() + rebuild_water_body_cache(self.fishing_area) def validate(self): self.validate_edit_access() @@ -42,14 +42,18 @@ def validate_blacklisted_fish_species(self): title=_("Invalid Species"), ) - def rebuild_water_body_cache(self): - # Invalidate Cache - frappe.cache().hdel("water_body_data", "all") - frappe.cache().hdel("water_body_data", self.fishing_area) - # Build Cache for all water bodies and fishing area wise - build_water_body_cache() - build_water_body_cache(fishing_area=self.fishing_area) +def rebuild_water_body_cache(fishing_area: str = None): + """ + Rebuilds water body cache for all water bodies **AND** fishing area wise. + """ + # Invalidate Cache + frappe.cache().hdel("water_body_data", "all") + build_water_body_cache() + + if fishing_area: + frappe.cache().hdel("water_body_data", fishing_area) + build_water_body_cache(fishing_area=fishing_area) def remove_outdated_information(): diff --git a/landa/water_body_management/doctype/water_body_management_local_organization/water_body_management_local_organization.py b/landa/water_body_management/doctype/water_body_management_local_organization/water_body_management_local_organization.py index d3f5a6b6..1b5e0cc0 100644 --- a/landa/water_body_management/doctype/water_body_management_local_organization/water_body_management_local_organization.py +++ b/landa/water_body_management/doctype/water_body_management_local_organization/water_body_management_local_organization.py @@ -5,6 +5,12 @@ # import frappe from frappe.model.document import Document +from landa.water_body_management.doctype.water_body.water_body import rebuild_water_body_cache + class WaterBodyManagementLocalOrganization(Document): - pass + def on_update(self): + rebuild_water_body_cache(self.fishing_area) + + def on_trash(self): + rebuild_water_body_cache(self.fishing_area) From 69fc83a26306d8b3baf739206ac5ae2528179a6b Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 18 Jul 2023 14:49:14 +0200 Subject: [PATCH 4/9] chore: build system in pyproject.toml --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 2da10f1c..edb9699a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,10 @@ dependencies = [ "thefuzz", ] +[build-system] +requires = ["flit_core >=3.4,<4"] +build-backend = "flit_core.buildapi" + [tool.black] line-length = 99 From 61d7d1ddf7737f25ae35d1cec435e90701fd0dc4 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:40:02 +0200 Subject: [PATCH 5/9] fix: remove duplicate location data --- .../water_body_management/doctype/water_body/water_body.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/landa/water_body_management/doctype/water_body/water_body.py b/landa/water_body_management/doctype/water_body/water_body.py index b9463a0c..fa87b903 100644 --- a/landa/water_body_management/doctype/water_body/water_body.py +++ b/landa/water_body_management/doctype/water_body/water_body.py @@ -1,6 +1,7 @@ # Copyright (c) 2021, Real Experts GmbH and contributors # For license information, please see license.txt from collections import defaultdict +from json import loads from typing import Dict, List import frappe @@ -171,9 +172,10 @@ def consolidate_water_body_data(water_body_data: List[Dict]) -> List[Dict]: def init_row(water_body_row: Dict) -> Dict: # Prepare row to have Water Body data (excluding child tables) water_body_copy = water_body_row.copy() + location = water_body_copy.pop("location", None) - if water_body_copy.location: - water_body_copy["geojson"] = frappe.parse_json(water_body_copy.location) + if location and isinstance(location, str): + water_body_copy["geojson"] = loads(location) for field in ( "fish_species", From a6bf6b5efecfd97a63213c9f87109423bd2c9f74 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:02:56 +0200 Subject: [PATCH 6/9] fix: add missing translations (LAN-72) --- landa/translations/de.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/landa/translations/de.csv b/landa/translations/de.csv index fa297be8..d8635c89 100644 --- a/landa/translations/de.csv +++ b/landa/translations/de.csv @@ -22,3 +22,4 @@ Current Public Information will be removed on this date,Aktuelle Informationen w Current Information Expires On,Aktuelle Informationen zurücksetzen am, Fish Species Short Codes,Fischart Kürzel, Water Body Export,Export Gewässerverzeichnis, +No permission to set Member Function Category {0},"Sie haben nicht die nötigen Rechte, um eine Mitgliedsfunktion der Kategorie {0} zu vergeben", From 9769ff0a604aa27a66ca98d70cb2df7d87742e6c Mon Sep 17 00:00:00 2001 From: diePuppe <95628567+diePuppe@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:24:17 +0200 Subject: [PATCH 7/9] feat: automatic year in catch log entry(LAN-44 ) (#227) Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --- .../doctype/catch_log_entry/catch_log_entry.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/landa/water_body_management/doctype/catch_log_entry/catch_log_entry.js b/landa/water_body_management/doctype/catch_log_entry/catch_log_entry.js index 0f2bf614..fe2727e2 100644 --- a/landa/water_body_management/doctype/catch_log_entry/catch_log_entry.js +++ b/landa/water_body_management/doctype/catch_log_entry/catch_log_entry.js @@ -21,5 +21,12 @@ frappe.ui.form.on("Catch Log Entry", { }); }); } + const today = new Date(); + const current_year = today.getFullYear(); + const current_month = today.getMonth(); + + if (!frm.doc.year) { + frm.set_value("year", current_month < 6 ? current_year - 1 : current_year); + } }, }); From 03864ec91399dbb8b4a96f028881a5dfc0a5a057 Mon Sep 17 00:00:00 2001 From: diePuppe <95628567+diePuppe@users.noreply.github.com> Date: Tue, 18 Jul 2023 17:08:07 +0200 Subject: [PATCH 8/9] feat: hide custom workspaces (LAN-45) (#232) Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --- landa/hooks.py | 3 +++ landa/patches.txt | 1 + .../set_hide_custom_in_user_workspaces.py | 17 +++++++++++++++++ landa/workspace.py | 13 +++++++++++++ 4 files changed, 34 insertions(+) create mode 100644 landa/patches/set_hide_custom_in_user_workspaces.py create mode 100644 landa/workspace.py diff --git a/landa/hooks.py b/landa/hooks.py index cfe3e93d..04a8a82a 100644 --- a/landa/hooks.py +++ b/landa/hooks.py @@ -288,6 +288,9 @@ "on_update": "landa.organization_management.user.user.on_update", "on_trash": "landa.organization_management.user.user.on_trash", }, + "Workspace": { + "validate": "landa.workspace.validate", + }, } # Scheduled Tasks diff --git a/landa/patches.txt b/landa/patches.txt index 43e00a99..991aaee7 100644 --- a/landa/patches.txt +++ b/landa/patches.txt @@ -24,3 +24,4 @@ landa.patches.delete_old_scheduled_job_logs landa.patches.update_system_settings landa.patches.delete_customized_workspaces # 2023-06-06 landa.patches.build_water_body_cache +landa.patches.set_hide_custom_in_user_workspaces diff --git a/landa/patches/set_hide_custom_in_user_workspaces.py b/landa/patches/set_hide_custom_in_user_workspaces.py new file mode 100644 index 00000000..d684713f --- /dev/null +++ b/landa/patches/set_hide_custom_in_user_workspaces.py @@ -0,0 +1,17 @@ +import frappe + +from landa.workspace import LANDA_WORKSPACES + + +def execute(): + """Hide custom reports in existing customized landa workspaces.""" + for workspace in frappe.get_all( + "Workspace", + filters={ + "for_user": ("is", "set"), + "hide_custom": 0, + "extends": ("in", LANDA_WORKSPACES), + }, + pluck="name", + ): + frappe.db.set_value("Workspace", workspace, "hide_custom", 1) diff --git a/landa/workspace.py b/landa/workspace.py new file mode 100644 index 00000000..d736686b --- /dev/null +++ b/landa/workspace.py @@ -0,0 +1,13 @@ +from frappe.desk.doctype.workspace.workspace import Workspace + +LANDA_WORKSPACES = ( + "Water Body Management", + "Organization Management", + "Order Management", +) + + +def validate(doc: Workspace, method=None) -> None: + # Custom reports (possibly of other users) should not be visible + if doc.for_user and doc.hide_custom == 0 and doc.extends in LANDA_WORKSPACES: + doc.hide_custom = 1 From 0065bc9483c740ac608d0aba8f24955eb7da9a6b Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 1 Aug 2023 12:47:27 +0200 Subject: [PATCH 9/9] fix: year in Catch Log Entry (LAN-44) --- .../doctype/catch_log_entry/catch_log_entry.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/landa/water_body_management/doctype/catch_log_entry/catch_log_entry.js b/landa/water_body_management/doctype/catch_log_entry/catch_log_entry.js index fe2727e2..50d3d299 100644 --- a/landa/water_body_management/doctype/catch_log_entry/catch_log_entry.js +++ b/landa/water_body_management/doctype/catch_log_entry/catch_log_entry.js @@ -9,7 +9,13 @@ frappe.ui.form.on("Catch Log Entry", { }, onload: (frm) => { if (frm.is_new() && !frm.doc.year) { - frm.set_value("year", moment().year() - 1); + const today = new Date(); + const current_year = today.getFullYear(); + const current_month = today.getMonth(); + + if (!frm.doc.year) { + frm.set_value("year", current_month < 6 ? current_year - 1 : current_year); + } } }, refresh: (frm) => { @@ -21,12 +27,5 @@ frappe.ui.form.on("Catch Log Entry", { }); }); } - const today = new Date(); - const current_year = today.getFullYear(); - const current_month = today.getMonth(); - - if (!frm.doc.year) { - frm.set_value("year", current_month < 6 ? current_year - 1 : current_year); - } }, });