This commit is contained in:
Dave 2025-03-13 23:54:50 +01:00
commit ddf8a837fb
3 changed files with 751 additions and 151 deletions

View File

@ -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
}

View File

@ -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]

View File

@ -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()
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
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])
# 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,54 +125,58 @@ 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
params = (from_date, to_date, user_id)
if considered_article_ids:
sql_query += " AND id NOT IN %s"
sql_query += " AND a.id NOT IN %s"
params += (tuple(considered_article_ids),)
# 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
)
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 []
# 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
"hours": qty,
"customer": item.get("customer", "Unbekannt"),
"description": item.get("description", "Keine Beschreibung")
}
ticket_hours.append(work_item)
@ -248,9 +184,6 @@ def get_ticket_work_hours(employee, from_date, to_date):
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()
@ -835,5 +773,3 @@ def get_documentation_html(it_landscape):