From 294c640096ed7edf7a63dddd111f69a2a0b2641d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rene=20Ka=C3=9Feb=C3=B6hmer?= Date: Wed, 25 Jun 2025 14:00:36 +0200 Subject: [PATCH] first success maintenance plan --- .../SN_SCINstalledBase__c.py | 12 +++++ .../fill_fields_and_insert.py | 46 +++++++++++++++++++ prepared_steps/1_extract_data/queries.json | 7 ++- 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 prepared_steps/0_cleansing_scripts/SN_SCINstalledBase__c.py diff --git a/prepared_steps/0_cleansing_scripts/SN_SCINstalledBase__c.py b/prepared_steps/0_cleansing_scripts/SN_SCINstalledBase__c.py new file mode 100644 index 0000000..c93a611 --- /dev/null +++ b/prepared_steps/0_cleansing_scripts/SN_SCINstalledBase__c.py @@ -0,0 +1,12 @@ +import pandas as pd + +# Load the CSV file +df = pd.read_csv('../1_extract_data/results/SCInstalledBase__c.csv') + +# Find duplicates based on SerialNo__c (excluding empty/NaN) +duplicates = df[df.duplicated(subset=['SerialNo__c'], keep=False) & df['SerialNo__c'].notna() & (df['SerialNo__c'] != '')] +duplicates.to_csv('results/duplicates.csv', index=False) + +# Find rows where SerialNo__c is empty or NaN +empty_serials = df[df['SerialNo__c'].isna() | (df['SerialNo__c'] == '')] +empty_serials.to_csv('results/empty_serials.csv', index=False) \ No newline at end of file diff --git a/prepared_steps/19_create_maintenance_plan/fill_fields_and_insert.py b/prepared_steps/19_create_maintenance_plan/fill_fields_and_insert.py index 7409cb2..aef8d85 100644 --- a/prepared_steps/19_create_maintenance_plan/fill_fields_and_insert.py +++ b/prepared_steps/19_create_maintenance_plan/fill_fields_and_insert.py @@ -3,6 +3,20 @@ import argparse from sys import path path.append('../..') from utils import bulk_insert_records +from datetime import datetime, timedelta + +# Find last maintenance/order date for each ServiceContractId +def get_last_maintenance_date(service_contract_id): + # Try to find in LastMaintenanceInformation + lm_rows = df_lm[df_lm['Order__r.Contract__c'] == service_contract_id] + if not lm_rows.empty: + # Use the most recent Order__r.Closed__c + return lm_rows['Order__r.Closed__c'].max() + # If not found, try LastOrderInformation + lo_rows = df_lo[df_lo['Contract__c'] == service_contract_id] + if not lo_rows.empty: + return lo_rows['Closed__c'].max() + return None if __name__ == '__main__': @@ -20,6 +34,7 @@ if __name__ == '__main__': #reindex_columns_sc = ['sf__Id','sf__Created','PKey__c', 'BillingCountryCode', 'Term', 'EndDate', 'StartDate', 'AccountId', 'Service_Recipient__c', 'IoT_Registration_Status__c', 'Name', 'Pricebook2Id', 'TemplateId__c'] #ServiceContract.PKey__c,StartDate,EndDate,AccountId,MaintenanceWindowEndDays,MaintenanceWindowStartDays,GenerationTimeframe,Frequency,GenerationTimeframeType,WorkTypeId reindex_columns_mp = ['ServiceContract.PKey__c', 'StartDate', 'EndDate', 'AccountId', 'MaintenanceWindowEndDays', 'MaintenanceWindowStartDays', 'GenerationTimeframe', 'Frequency', 'GenerationTimeframeType', 'WorkTypeId'] + reindex_columns_lastmaintenance = [] # Reindex the columns to match the desired format @@ -29,6 +44,9 @@ if __name__ == '__main__': # Only load 'sf__Id' and 'PKey__c' from the ServiceContract CSV df_sc = pd.read_csv('../16_insert_servicecontract/successful_records.csv', usecols=['sf__Id', 'PKey__c']) + # Load LastMaintenanceInformation and LastOrderInformation CSVs for NextSuggestedMaintenanceDate calculation + df_lm = pd.read_csv('../1_extract_data/results/LastMaintenanceInformation.csv', usecols=['Id', 'Order__r.Closed__c', 'Order__r.Contract__c']) + df_lo = pd.read_csv('../1_extract_data/results/LastOrderInformation.csv', usecols=['Id', 'Closed__c', 'Contract__c']) print(df_sc) print(df_mp) @@ -48,6 +66,34 @@ if __name__ == '__main__': merged_df_mp = merged_df_mp.drop('ServiceContract.PKey__c', axis=1) merged_df_mp = merged_df_mp.drop('PKey__c', axis=1) + def get_next_suggested_maintenance_date(service_contract_id): + # Try to find in LastMaintenanceInformation + lm_rows = df_lm[df_lm['Order__r.Contract__c'] == service_contract_id] + if not lm_rows.empty: + last_date = lm_rows['Order__r.Closed__c'].max() + else: + # If not found, try LastOrderInformation + lo_rows = df_lo[df_lo['Contract__c'] == service_contract_id] + if not lo_rows.empty: + last_date = lo_rows['Closed__c'].max() + else: + last_date = None + + if pd.notnull(last_date): + try: + dt = pd.to_datetime(last_date) + next_date = dt + pd.DateOffset(years=1) + return next_date.strftime('%Y-%m-%d') + except Exception: + pass + # If no date found or parsing fails, use today + next_date = datetime.today() + return next_date.strftime('%Y-%m-%d') + + merged_df_mp['NextSuggestedMaintenanceDate'] = merged_df_mp['ServiceContractId'].apply(get_next_suggested_maintenance_date) + + merged_df_mp['DoesAutoGenerateWorkOrders'] = True + #transform values into int merged_df_mp['MaintenanceWindowEndDays'] = pd.to_numeric(merged_df_mp['MaintenanceWindowEndDays'], errors='coerce').fillna(0).astype(int) merged_df_mp['MaintenanceWindowStartDays'] = pd.to_numeric(merged_df_mp['MaintenanceWindowStartDays'], errors='coerce').fillna(0).astype(int) diff --git a/prepared_steps/1_extract_data/queries.json b/prepared_steps/1_extract_data/queries.json index 631aca6..4b1eb90 100644 --- a/prepared_steps/1_extract_data/queries.json +++ b/prepared_steps/1_extract_data/queries.json @@ -5,7 +5,7 @@ "query": "SELECT Id, City__c, Country__c, GeoY__c, GeoX__c, PostalCode__c, Street__c, Extension__c, HouseNo__c, FlatNo__c, Floor__c FROM SCInstalledBaseLocation__c WHERE Country__c = '{country}' limit 3" },{ "sobject": "SCInstalledBase__c", - "query": "SELECT Id, Name, CommissioningDate__c,InstallationDate__c,ProductEnergy__c, ProductUnitClass__c,ArticleNo__c,SerialNo__c, SerialNoException__c, ProductUnitType__c, InstalledBaseLocation__c, WarrantyDuration__c, GuaranteeStandard__c, GuaranteeExtended__c FROM SCInstalledBase__c WHERE Country__c = '{country}' limit 3" + "query": "SELECT Id, Name, CommissioningDate__c,InstallationDate__c,ProductEnergy__c, ProductUnitClass__c,ArticleNo__c,SerialNo__c, SerialNoException__c, ProductUnitType__c, InstalledBaseLocation__c, WarrantyDuration__c, GuaranteeStandard__c, GuaranteeExtended__c FROM SCInstalledBase__c WHERE Country__c = '{country}'" },{ "sobject": "Asset", "query": "SELECT Id, Serialnumber FROM Asset WHERE Location.ParentLocation.Name LIKE '%{country}'" @@ -60,7 +60,10 @@ "query": "SELECT Id, Name, Brand__c, CertificationId__c, Combined__c, OrderType__c, QualificationProfile__c, ProductUnitType__c, ProductUnitClass__c FROM SCQualificationSpecification__c WHERE Country__c = '{country}'" },{ "sobject": "LastMaintenanceInformation", - "query": "SELECT Id, InstalledBase__r.SerialNo__c, Order__r.Closed__c FROM SCOrderItem__c WHERE Order__r.Status__c IN ('5506', '5508') AND InstalledBase__r.SerialNo__c != null AND Order__r.Type__c = '5707' AND Order__r.Country__c = '{country}'" + "query": "SELECT Id, InstalledBase__r.SerialNo__c, Order__r.Closed__c, Order__r.Contract__c FROM SCOrderItem__c WHERE Order__r.Status__c IN ('5506', '5508') AND InstalledBase__r.SerialNo__c != null AND Order__r.Type__c = '5707' AND Order__r.Country__c = '{country}'" + },{ + "sobject": "LastOrderInformation", + "query": "SELECT Id, Closed__c, Contract__c FROM SCOrder__c WHERE Status__c IN ('5506', '5508') AND Contract__c != null AND Closed__c = LAST_N_YEARS:10 AND Country__c = '{country}'" },{ "sobject": "WorkType", "useREST": true,