From 3b4e0dd7554e5dcbd6cc0b5a3d425f8bb50ead74 Mon Sep 17 00:00:00 2001 From: Beate Trenziok Date: Fri, 4 Oct 2024 12:42:52 +0200 Subject: [PATCH 1/2] Anpassung Surcharge --- msp/msp/custom/delivery_note_item.json | 624 ++++++++++++++++++ .../auto_invoice_generator.py | 42 +- 2 files changed, 665 insertions(+), 1 deletion(-) create mode 100644 msp/msp/custom/delivery_note_item.json diff --git a/msp/msp/custom/delivery_note_item.json b/msp/msp/custom/delivery_note_item.json new file mode 100644 index 0000000..dd327dc --- /dev/null +++ b/msp/msp/custom/delivery_note_item.json @@ -0,0 +1,624 @@ +{ + "custom_fields": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2024-10-04 08:33:37.874173", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Delivery Note Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "custom_created_from_service_report_item", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 77, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "pick_list_item", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Created from Service Report Item", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2024-10-04 08:33:37.874173", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-custom_created_from_service_report_item", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2023-02-14 11:47:25.516259", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Delivery Note Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "ignore_surcharges", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 72, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "service_report_item_hours", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Ignore Surcharges", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2023-02-14 11:47:25.516259", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-ignore_surcharges", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2022-09-13 12:10:36.651576", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Delivery Note Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "column_break_66", + "fieldtype": "Column Break", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 67, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "dn_detail", + "is_system_generated": 1, + "is_virtual": 0, + "label": null, + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-09-13 12:10:36.651576", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-column_break_66", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2022-09-13 12:08:59.893790", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Delivery Note Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "service_report_item_hours", + "fieldtype": "Float", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 72, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "service_report_item_end", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Service Report Item Hours", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-09-13 12:08:59.893790", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-service_report_item_hours", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2022-09-13 12:08:59.066768", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Delivery Note Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "service_report_item_end", + "fieldtype": "Datetime", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 71, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "service_report_item_begin", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Service Report Item End", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-09-13 12:08:59.066768", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-service_report_item_end", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2022-09-13 12:08:58.297123", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Delivery Note Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "service_report_item_begin", + "fieldtype": "Datetime", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 70, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "against_service_report_item", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Service Report Item Begin", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-09-13 12:08:58.297123", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-service_report_item_begin", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2022-09-13 12:08:57.535302", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Delivery Note Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "against_service_report_item", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 69, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "agains_service_report", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Against Service Report Item", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-09-13 12:08:57.535302", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-against_service_report_item", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2022-09-13 12:08:56.616015", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Delivery Note Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "agains_service_report", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 68, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "column_break_66", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Agains Service Report", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-09-13 12:08:56.616015", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-agains_service_report", + "no_copy": 0, + "non_negative": 0, + "options": "Service Report", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Delivery Note Item", + "links": [], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2024-10-04 08:33:37.725550", + "default_value": null, + "doc_type": "Delivery Note Item", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2024-10-04 08:33:37.725550", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-main-field_order", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "field_order", + "property_type": "Data", + "row_name": null, + "value": "[\"barcode\", \"has_item_scanned\", \"item_code\", \"item_name\", \"col_break1\", \"customer_item_code\", \"section_break_6\", \"description\", \"brand\", \"item_group\", \"image_section\", \"image\", \"image_view\", \"quantity_and_rate\", \"qty\", \"stock_uom\", \"col_break2\", \"uom\", \"conversion_factor\", \"stock_qty_sec_break\", \"stock_qty\", \"stock_qty_col_break\", \"returned_qty\", \"section_break_17\", \"price_list_rate\", \"base_price_list_rate\", \"discount_and_margin\", \"margin_type\", \"margin_rate_or_amount\", \"rate_with_margin\", \"column_break_19\", \"discount_percentage\", \"discount_amount\", \"base_rate_with_margin\", \"section_break_1\", \"rate\", \"amount\", \"col_break3\", \"base_rate\", \"base_amount\", \"pricing_rules\", \"stock_uom_rate\", \"is_free_item\", \"grant_commission\", \"section_break_25\", \"net_rate\", \"net_amount\", \"item_tax_template\", \"column_break_28\", \"base_net_rate\", \"base_net_amount\", \"billed_amt\", \"incoming_rate\", \"item_weight_details\", \"weight_per_unit\", \"total_weight\", \"column_break_21\", \"weight_uom\", \"warehouse_and_reference\", \"warehouse\", \"target_warehouse\", \"quality_inspection\", \"col_break4\", \"allow_zero_valuation_rate\", \"against_sales_order\", \"so_detail\", \"against_sales_invoice\", \"si_detail\", \"dn_detail\", \"column_break_66\", \"agains_service_report\", \"against_service_report_item\", \"service_report_item_begin\", \"service_report_item_end\", \"service_report_item_hours\", \"ignore_surcharges\", \"pick_list_item\", \"created_from_service_report_item\", \"section_break_40\", \"pick_serial_and_batch\", \"serial_and_batch_bundle\", \"use_serial_batch_fields\", \"column_break_eaoe\", \"section_break_qyjv\", \"serial_no\", \"column_break_rxvc\", \"batch_no\", \"available_qty_section\", \"actual_batch_qty\", \"actual_qty\", \"installed_qty\", \"item_tax_rate\", \"column_break_atna\", \"packed_qty\", \"received_qty\", \"accounting_details_section\", \"expense_account\", \"column_break_71\", \"internal_transfer_section\", \"material_request\", \"purchase_order\", \"column_break_82\", \"purchase_order_item\", \"material_request_item\", \"accounting_dimensions_section\", \"cost_center\", \"dimension_col_break\", \"project\", \"section_break_72\", \"page_break\"]" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2022-07-31 20:17:44.978675", + "default_value": null, + "doc_type": "Delivery Note Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "barcode", + "idx": 0, + "is_system_generated": 0, + "modified": "2024-06-26 15:41:46.544265", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-barcode-hidden", + "owner": "D.Malinowski@itsdave.de", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2022-07-31 20:17:45.561455", + "default_value": null, + "doc_type": "Delivery Note Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "target_warehouse", + "idx": 0, + "is_system_generated": 0, + "modified": "2024-06-26 15:41:46.528591", + "modified_by": "Administrator", + "module": null, + "name": "Delivery Note Item-target_warehouse-hidden", + "owner": "D.Malinowski@itsdave.de", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "1" + } + ], + "sync_on_migrate": 1 +} \ No newline at end of file diff --git a/msp/msp/doctype/auto_invoice_generator/auto_invoice_generator.py b/msp/msp/doctype/auto_invoice_generator/auto_invoice_generator.py index 08c8bde..2720b07 100644 --- a/msp/msp/doctype/auto_invoice_generator/auto_invoice_generator.py +++ b/msp/msp/doctype/auto_invoice_generator/auto_invoice_generator.py @@ -406,14 +406,54 @@ class AutoInvoiceGenerator(Document): return invoice_count def separate_items_by_group(self, items, group_filter): + print("Original Items:", [item.name for item in items]) + group_items = [] remaining_items = items.copy() + + # Verarbeite nur die Arbeitsartikel for item in remaining_items: - if item.item_group in group_filter: + print("Processing Item:", item.name) + + # Füge nur Artikel aus der gewünschten Gruppe hinzu + if item.item_group in group_filter and not item.custom_created_from_service_report_item: group_items.append(self.create_invoice_doc_item(item)) + print(f"Added {item.name} to group_items") items.remove(item) + + # Finde die zugehörigen Zuschläge für diesen Artikel und füge sie direkt hinzu + related_surcharges = [s for s in items if s.custom_created_from_service_report_item == item.name] + for surcharge_item in related_surcharges: + group_items.append(self.create_invoice_doc_item(surcharge_item)) + print(f"Added surcharge {surcharge_item.name} directly after {item.name}") + items.remove(surcharge_item) + + print("Final Group Items:", [item.name if item else "None" for item in group_items]) + print(group_items) + print("Remaining Items after removal:", [item.name for item in items]) + return group_items, items + + + + # def separate_items_by_group(self, items, group_filter): + # print(items) + # print(group_filter) + # print("Original Items:", [item.name for item in items]) + # group_items = [] + # remaining_items = items.copy() + # for item in remaining_items: + # print("Processing Item:", item.name) + # if item.item_group in group_filter: + # group_items.append(self.create_invoice_doc_item(item)) + # print(f"Added {item.name} to group_items") + # items.remove(item) + # print(group_items) + # print(items) + # return group_items, items + + def separate_sales_order_items(self, items): sales_order_items = [self.create_invoice_doc_item(item) for item in items if item.against_sales_order] remaining_items = [item for item in items if not item.against_sales_order] From 5830529ca8d6129e096749304c9105b7fe8fe801 Mon Sep 17 00:00:00 2001 From: Beate Trenziok Date: Fri, 7 Mar 2025 10:51:02 +0100 Subject: [PATCH 2/2] Anpassungen detailierte Items, Bug Tagesumbruch --- msp/tools.py | 236 +++++++++++++++++++-------------------------------- 1 file changed, 87 insertions(+), 149 deletions(-) diff --git a/msp/tools.py b/msp/tools.py index 35dbc85..67402b0 100644 --- a/msp/tools.py +++ b/msp/tools.py @@ -1,6 +1,7 @@ import frappe import json from datetime import datetime, date, timedelta +import math from frappe.database import get_db from erpnext.stock.utils import get_stock_balance @@ -43,147 +44,78 @@ def get_hours_from_ticket_service_reports(employee, from_date, to_date): to_date = to_date + timedelta(days=1) - timedelta(seconds=1) - # Hours from the service reports - service_report_hours = get_service_report_work(employee,from_date, to_date) - - # Hours from the tickets with status open + # Stunden aus Service Reports und Tickets abrufen + service_report_hours = get_service_report_work(employee, from_date, to_date) ticket_hours = get_ticket_work_hours(employee, from_date, to_date) - # Combine the results combined_hours = service_report_hours + ticket_hours hours_dict = {} + detailed_entries = [] # Liste für Kalendereinträge if combined_hours: for entry in combined_hours: if entry['end'] and entry['begin'] and entry['end'] >= from_date and entry['begin'] <= to_date: - date_key = entry['begin'].date() - if date_key not in hours_dict: - hours_dict[date_key] = 0 - hours_dict[date_key] += entry['hours'] - hours_sum = sum([x['hours'] for x in combined_hours if x['end'] and x['begin'] and x['end'] >= from_date and x['begin'] <= to_date]) + current_time = entry['begin'] + + while current_time < entry['end']: + date_key = current_time.date() + next_day = (current_time + timedelta(days=1)).replace(hour=0, minute=0, second=0) + + if date_key not in hours_dict: + hours_dict[date_key] = 0 + + # Bestimme die tatsächliche Endzeit für diesen Tag + actual_end = min(entry['end'], next_day) + + # Berechne die Stunden für diesen Zeitraum + work_hours = (actual_end - current_time).total_seconds() / 3600 + + # Runde auf Viertelstunden + work_hours = math.ceil(work_hours * 4) / 4 + + hours_dict[date_key] += work_hours + + # Kalendereintrag hinzufügen + detailed_entries.append({ + "employee": employee, + "begin": current_time, + "end": actual_end, + "hours": work_hours, + "customer": entry.get("customer", "Unbekannt"), + "description": entry.get("description", "Keine Beschreibung") + }) + + current_time = next_day # Zum nächsten Tag übergehen + + # Gesamtstunden berechnen (nach Rundung) + hours_sum = sum(hours_dict.values()) else: hours_sum = 0 sorted_hours_dict = dict(sorted(hours_dict.items())) - print(hours_sum) - print(hours_dict) - return sorted_hours_dict, hours_sum + print(sorted_hours_dict) + + return sorted_hours_dict, hours_sum, detailed_entries def get_service_report_work(employee, from_date, to_date): result = frappe.db.sql(""" - SELECT `begin`, `end`, `hours` - FROM `tabService Report Work` - WHERE parenttype = 'Service Report' - AND parent IN (SELECT name FROM `tabService Report` - WHERE employee = %s - AND (`begin` BETWEEN %s AND %s OR `end` BETWEEN %s AND %s)) + SELECT srw.`begin`, srw.`end`, srw.`hours`, sr.customer, srw.description + FROM `tabService Report Work` srw + JOIN `tabService Report` sr ON sr.name = srw.parent + WHERE sr.employee = %s + AND (srw.`begin` BETWEEN %s AND %s OR srw.`end` BETWEEN %s AND %s) + + """, (employee, from_date, to_date, from_date, to_date), as_dict=True) return result -# def get_ticket_work_hours(employee, from_date, to_date): -# if isinstance(from_date, str): -# from_date = datetime.strptime(from_date, "%Y-%m-%d") -# if isinstance(to_date, str): -# to_date = datetime.strptime(to_date, "%Y-%m-%d") - -# to_date = to_date + timedelta(days=1) - timedelta(seconds=1) - -# user = frappe.get_all("OTRSConnect User", filters={"erpnext_employee": employee}, fields=["id"]) -# if not user: -# return [] -# user_id = user[0].id -# print(user_id) - -# result = frappe.db.sql(""" -# SELECT `create_time`, `time_unit` -# FROM `tabOTRSConnect Article` -# WHERE -# create_time BETWEEN %s AND %s -# AND create_by = %s; -# """, (from_date, to_date, user_id), as_dict=True) - -# # List for saving the processed ticket data -# ticket_hours = [] - -# for item in result: - -# # Calculate the hours and working times (15 minutes equals 0.25 hours) -# qty = float(item['time_unit']) / 4.0 -# work_begin = item['create_time'] - timedelta(hours=qty) - -# # Create the work item dictionary -# work_item = { -# "employee": employee, -# "begin": work_begin, -# "end": item['create_time'], -# "hours": qty -# } - - -# ticket_hours.append(work_item) - -# return ticket_hours - - -# def get_ticket_work_hours(employee, from_date, to_date): -# if isinstance(from_date, str): -# from_date = datetime.strptime(from_date, "%Y-%m-%d") -# if isinstance(to_date, str): -# to_date = datetime.strptime(to_date, "%Y-%m-%d") - -# to_date = to_date + timedelta(days=1) - timedelta(seconds=1) - -# user = frappe.get_all("OTRSConnect User", filters={"erpnext_employee": employee}, fields=["id"]) -# if not user: -# return [] -# user_id = user[0].id -# print(user_id) - -# # Fetch all article IDs that are already considered in service reports within the given date range -# considered_articles = frappe.db.sql(""" -# SELECT otrs_article -# FROM `tabService Report Work` -# WHERE otrs_article IS NOT NULL AND `begin` BETWEEN %s AND %s -# """, (from_date, to_date), as_list=True) - -# # Flatten the list of considered article IDs -# considered_article_ids = [article[0] for article in considered_articles] - -# # Fetch OTRSConnect Articles, excluding those already in service reports -# result = frappe.db.sql(""" -# SELECT `id`, `create_time`, `time_unit` -# FROM `tabOTRSConnect Article` -# WHERE -# create_time BETWEEN %s AND %s -# AND create_by = %s -# AND id NOT IN %s; -# """, (from_date, to_date, user_id, tuple(considered_article_ids)), as_dict=True) - -# # List for saving the processed ticket data -# ticket_hours = [] - -# for item in result: -# # Calculate the hours and working times (15 minutes equals 0.25 hours) -# qty = float(item['time_unit']) / 4.0 -# work_begin = item['create_time'] - timedelta(hours=qty) - -# # Create the work item dictionary -# work_item = { -# "employee": employee, -# "begin": work_begin, -# "end": item['create_time'], -# "hours": qty -# } - -# ticket_hours.append(work_item) - -# return ticket_hours - def get_ticket_work_hours(employee, from_date, to_date): + print(f"DEBUG: Start get_ticket_work_hours for employee {employee}, from {from_date} to {to_date}") + if isinstance(from_date, str): from_date = datetime.strptime(from_date, "%Y-%m-%d") if isinstance(to_date, str): @@ -193,64 +125,65 @@ def get_ticket_work_hours(employee, from_date, to_date): user = frappe.get_all("OTRSConnect User", filters={"erpnext_employee": employee}, fields=["id"]) if not user: + print("DEBUG: No OTRSConnect User found for this employee.") return [] - user_id = user[0].id - print(user_id) - # Fetch all article IDs that are already considered in service reports within the given date range + user_id = user[0].id + considered_articles = frappe.db.sql(""" SELECT otrs_article FROM `tabService Report Work` WHERE otrs_article IS NOT NULL AND `begin` BETWEEN %s AND %s """, (from_date, to_date), as_list=True) - # Flatten the list of considered article IDs considered_article_ids = [article[0] for article in considered_articles] - # Build the SQL query for OTRSConnect Articles sql_query = """ - SELECT `id`, `create_time`, `time_unit` - FROM `tabOTRSConnect Article` + SELECT + a.`id`, + a.`create_time`, + a.`time_unit`, + a.`a_body` AS description, + t.`erpnext_customer` AS customer + FROM `tabOTRSConnect Article` a + LEFT JOIN `tabOTRSConnect Ticket` t ON a.`ticket_id` = t.`name` WHERE - create_time BETWEEN %s AND %s - AND create_by = %s + a.create_time BETWEEN %s AND %s + AND a.create_by = %s + AND a.docstatus IN (0, 1) """ - - # Add the NOT IN condition if there are considered_article_ids - if considered_article_ids: - sql_query += " AND id NOT IN %s" - # Execute the query - result = frappe.db.sql( - sql_query, - (from_date, to_date, user_id) + (tuple(considered_article_ids),) if considered_article_ids else (from_date, to_date, user_id), - as_dict=True - ) - - # List for saving the processed ticket data + params = (from_date, to_date, user_id) + if considered_article_ids: + sql_query += " AND a.id NOT IN %s" + params += (tuple(considered_article_ids),) + + result = frappe.db.sql(sql_query, params, as_dict=True) + + if not result: + print("DEBUG: No articles found in `tabOTRSConnect Article` for the given conditions.") + return [] + ticket_hours = [] for item in result: - # Calculate the hours and working times (15 minutes equals 0.25 hours) qty = float(item['time_unit']) / 4.0 work_begin = item['create_time'] - timedelta(hours=qty) - # Create the work item dictionary work_item = { "employee": employee, "begin": work_begin, "end": item['create_time'], - "hours": qty + "hours": qty, + "customer": item.get("customer", "Unbekannt"), + "description": item.get("description", "Keine Beschreibung") } - + ticket_hours.append(work_item) return ticket_hours - - - @frappe.whitelist() def get_target_hours(employee, from_date, to_date): from_date = from_date.date() @@ -338,7 +271,8 @@ def compare_hours(employee, from_date, to_date): # Working hours - service_hours, service_hours_sum = get_hours_from_ticket_service_reports(employee, from_date, to_date) + service_hours, service_hours_sum, detailed_entries = get_hours_from_ticket_service_reports(employee, from_date, to_date) + print(service_hours, service_hours_sum, detailed_entries) # Agreed hours target_hours = get_target_hours(employee, from_date, to_date) @@ -367,7 +301,11 @@ def compare_hours(employee, from_date, to_date): current_date += timedelta(days=1) - return {"daily_dict": daily_dict, "period_dict": period_dict} + return { + "daily_dict": daily_dict, + "period_dict": period_dict, + "detailed_entries": detailed_entries + } @frappe.whitelist() @@ -620,7 +558,7 @@ def get_status_from_ticket(): print(f"{field}: {value}") print("---") - +