273 lines
12 KiB
Python
273 lines
12 KiB
Python
|
|
# -*- coding: utf-8 -*-
|
||
|
|
|
||
|
|
from odoo import models, fields, api
|
||
|
|
from datetime import datetime
|
||
|
|
import logging
|
||
|
|
_logger = logging.getLogger(__name__)
|
||
|
|
class SurveyExportWizard(models.TransientModel):
|
||
|
|
_name = "survey.export.wizard"
|
||
|
|
_description = "Survey Export Wizard"
|
||
|
|
|
||
|
|
survey_id = fields.Many2one('survey.survey', string='Survey', required=True)
|
||
|
|
date_from = fields.Datetime(string='From Date')
|
||
|
|
date_to = fields.Datetime(string='To Date')
|
||
|
|
export_type = fields.Selection([
|
||
|
|
('completed', 'Only Completed Surveys'),
|
||
|
|
('group_by_partner', 'Group By Partner')
|
||
|
|
], string='Export Type', default='completed', required=True)
|
||
|
|
type_export = fields.Selection([('session','session'),('no_session','no session')], string='Export')
|
||
|
|
def export_to_excel(self):
|
||
|
|
return self.env.ref('survey_xls_report.action_survey_xls_report').report_action(self)
|
||
|
|
|
||
|
|
processed_count = fields.Integer('Processed Surveys', readonly=True)
|
||
|
|
updated_records = fields.Integer('Updated Records', readonly=True)
|
||
|
|
no_match_count = fields.Integer('No Matches', readonly=True)
|
||
|
|
error_count = fields.Integer('Errors', readonly=True)
|
||
|
|
status = fields.Selection([
|
||
|
|
('draft', 'Draft'),
|
||
|
|
('processing', 'Processing'),
|
||
|
|
('done', 'Completed')
|
||
|
|
], default='draft', readonly=True)
|
||
|
|
details = fields.Text('Processing Details', readonly=True)
|
||
|
|
|
||
|
|
def process_and_export(self):
|
||
|
|
self.ensure_one()
|
||
|
|
|
||
|
|
# Update status to processing
|
||
|
|
self.write({'status': 'processing'})
|
||
|
|
|
||
|
|
# Build domain for survey inputs - ONLY COMPLETED SURVEYS
|
||
|
|
domain = [
|
||
|
|
('survey_id', '=', self.survey_id.id),
|
||
|
|
('state', '=', 'done') # Only completed surveys
|
||
|
|
]
|
||
|
|
if self.date_from:
|
||
|
|
domain.append(('create_date', '>=', self.date_from))
|
||
|
|
if self.date_to:
|
||
|
|
domain.append(('create_date', '<=', self.date_to))
|
||
|
|
|
||
|
|
# Get only completed survey inputs
|
||
|
|
survey_inputs = self.env['survey.user_input'].search(domain)
|
||
|
|
|
||
|
|
processed_count = 0
|
||
|
|
updated_records = 0
|
||
|
|
no_match_count = 0
|
||
|
|
error_count = 0
|
||
|
|
details = []
|
||
|
|
|
||
|
|
# Process each completed survey input
|
||
|
|
for user_input in survey_inputs:
|
||
|
|
try:
|
||
|
|
name, dob = self._extract_survey_data(user_input)
|
||
|
|
|
||
|
|
if name and dob:
|
||
|
|
updated_count_local = self._update_info_model_status(name, dob, user_input)
|
||
|
|
|
||
|
|
if updated_count_local > 0:
|
||
|
|
updated_records += updated_count_local
|
||
|
|
details.append(f"✓ Survey {user_input.id}: Updated {updated_count_local} record(s) for {name}")
|
||
|
|
else:
|
||
|
|
no_match_count += 1
|
||
|
|
details.append(f"○ Survey {user_input.id}: No match found for {name}")
|
||
|
|
|
||
|
|
processed_count += 1
|
||
|
|
else:
|
||
|
|
if not name and not dob:
|
||
|
|
details.append(f"○ Survey {user_input.id}: Missing both name and DOB data")
|
||
|
|
elif not name:
|
||
|
|
details.append(f"○ Survey {user_input.id}: Missing name data")
|
||
|
|
no_match_count += 1
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
error_count += 1
|
||
|
|
details.append(f"✗ Survey {user_input.id}: Error - {str(e)}")
|
||
|
|
|
||
|
|
# Prepare results
|
||
|
|
summary = [
|
||
|
|
f"Processing Summary for Survey: {self.survey_id.title}",
|
||
|
|
f"=================================================",
|
||
|
|
f"Total Completed Surveys Processed: {processed_count}",
|
||
|
|
f"Records Updated: {updated_records}",
|
||
|
|
f"No Matches: {no_match_count}",
|
||
|
|
f"Errors: {error_count}",
|
||
|
|
"",
|
||
|
|
"Details:",
|
||
|
|
"========"
|
||
|
|
]
|
||
|
|
|
||
|
|
summary.extend(details)
|
||
|
|
|
||
|
|
# Update wizard results
|
||
|
|
self.write({
|
||
|
|
'processed_count': processed_count,
|
||
|
|
'updated_records': updated_records,
|
||
|
|
'no_match_count': no_match_count,
|
||
|
|
'error_count': error_count,
|
||
|
|
'details': '\n'.join(summary),
|
||
|
|
'status': 'done'
|
||
|
|
})
|
||
|
|
|
||
|
|
# Now export to Excel
|
||
|
|
return self.export_to_excel()
|
||
|
|
|
||
|
|
def _extract_survey_data(self, user_input):
|
||
|
|
"""
|
||
|
|
Extract name and date of birth from completed survey answers
|
||
|
|
"""
|
||
|
|
name = None
|
||
|
|
dob = None
|
||
|
|
|
||
|
|
# Debug: Print all questions and their types
|
||
|
|
print("=== ALL SURVEY QUESTIONS ===")
|
||
|
|
for line in user_input.user_input_line_ids:
|
||
|
|
print(
|
||
|
|
f"Question: '{line.question_id.title}' | Type: {line.question_id.question_type} | Value: {self._get_debug_value(line)}")
|
||
|
|
|
||
|
|
# Common keywords for name and DOB questions
|
||
|
|
name_keywords = [
|
||
|
|
'គោត្ដនាម និងនាម៖', 'name', 'full name', 'employee name', 'participant name', 'ឈ្មោះ'
|
||
|
|
]
|
||
|
|
dob_keywords = [
|
||
|
|
'ថ្ថ្ងៃ ខែ ឆ្នាំកំណើត៖', 'date of birth', 'birthday', 'dob', 'birth', 'ថ្ងៃខែឆ្នាំកំណើត'
|
||
|
|
]
|
||
|
|
|
||
|
|
for line in user_input.user_input_line_ids:
|
||
|
|
question_title = line.question_id.title.strip() # Don't convert to lower for Khmer text
|
||
|
|
question_title_lower = question_title.lower()
|
||
|
|
|
||
|
|
# Extract name
|
||
|
|
if any(keyword in question_title or keyword in question_title_lower for keyword in name_keywords):
|
||
|
|
print("Found NAME question")
|
||
|
|
# Handle different question types for name
|
||
|
|
if hasattr(line, 'value_char_box') and line.value_char_box:
|
||
|
|
name = line.value_char_box.strip()
|
||
|
|
print(f"Name from char_box: '{name}'")
|
||
|
|
elif hasattr(line, 'value_text_box') and line.value_text_box:
|
||
|
|
name = line.value_text_box.strip()
|
||
|
|
print(f"Name from text_box: '{name}'")
|
||
|
|
elif hasattr(line, 'suggested_answer_id') and line.suggested_answer_id:
|
||
|
|
name = line.suggested_answer_id.value.strip()
|
||
|
|
print(f"Name from suggested_answer: '{name}'")
|
||
|
|
|
||
|
|
# Extract date of birth
|
||
|
|
elif any(keyword in question_title or keyword in question_title_lower for keyword in dob_keywords):
|
||
|
|
print("Found DOB question")
|
||
|
|
print(f"Question type: {line.question_id.question_type}")
|
||
|
|
|
||
|
|
# Handle different question types for date
|
||
|
|
if hasattr(line, 'value_date') and line.value_date:
|
||
|
|
dob = line.value_date
|
||
|
|
print(f"DOB from value_date: {dob}")
|
||
|
|
elif hasattr(line, 'value_datetime') and line.value_datetime:
|
||
|
|
# If datetime, extract just the date part
|
||
|
|
if isinstance(line.value_datetime, datetime):
|
||
|
|
dob = line.value_datetime.date()
|
||
|
|
print(f"DOB from datetime: {dob}")
|
||
|
|
else:
|
||
|
|
dob = line.value_datetime
|
||
|
|
print(f"DOB from value_datetime: {dob}")
|
||
|
|
elif hasattr(line, 'value_char_box') and line.value_char_box:
|
||
|
|
# Try to parse date from char box
|
||
|
|
date_str = line.value_char_box.strip()
|
||
|
|
print(f"DOB from char_box (string): '{date_str}'")
|
||
|
|
# You might need to parse this string to a date object
|
||
|
|
# Example: if date_str is in format '2023-12-25'
|
||
|
|
try:
|
||
|
|
from datetime import datetime
|
||
|
|
dob = datetime.strptime(date_str, '%d/%m/%Y').date()
|
||
|
|
print(f"Parsed DOB: {dob}")
|
||
|
|
except:
|
||
|
|
print("Could not parse date string")
|
||
|
|
elif hasattr(line, 'value_text_box') and line.value_text_box:
|
||
|
|
# Try to parse date from text box
|
||
|
|
date_str = line.value_text_box.strip()
|
||
|
|
print(f"DOB from text_box (string): '{date_str}'")
|
||
|
|
try:
|
||
|
|
from datetime import datetime
|
||
|
|
dob = datetime.strptime(date_str, '%d/%m/%Y').date()
|
||
|
|
print(f"Parsed DOB: {dob}")
|
||
|
|
except:
|
||
|
|
print("Could not parse date string")
|
||
|
|
print("=================",name ,"===dob",dob)
|
||
|
|
return name, dob
|
||
|
|
|
||
|
|
def _get_debug_value(self, line):
|
||
|
|
"""Helper method to get the value from a survey line for debugging"""
|
||
|
|
if hasattr(line, 'value_char_box') and line.value_char_box:
|
||
|
|
return f"char_box: '{line.value_char_box}'"
|
||
|
|
elif hasattr(line, 'value_text_box') and line.value_text_box:
|
||
|
|
return f"text_box: '{line.value_text_box}'"
|
||
|
|
elif hasattr(line, 'value_date') and line.value_date:
|
||
|
|
return f"date: {line.value_date}"
|
||
|
|
elif hasattr(line, 'value_datetime') and line.value_datetime:
|
||
|
|
return f"datetime: {line.value_datetime}"
|
||
|
|
elif hasattr(line, 'value_numerical_box') and line.value_numerical_box is not None:
|
||
|
|
return f"numerical: {line.value_numerical_box}"
|
||
|
|
elif hasattr(line, 'suggested_answer_id') and line.suggested_answer_id:
|
||
|
|
return f"suggested: '{line.suggested_answer_id.value}'"
|
||
|
|
else:
|
||
|
|
return "no_value"
|
||
|
|
|
||
|
|
def _update_info_model_status(self, name, dob, survey_input):
|
||
|
|
"""
|
||
|
|
Update status in info model when name and DOB match
|
||
|
|
"""
|
||
|
|
if not name or not dob:
|
||
|
|
print(f"Skipping update - Missing data: name='{name}', dob='{dob}'")
|
||
|
|
return 0
|
||
|
|
|
||
|
|
try:
|
||
|
|
# Debug: Print search criteria
|
||
|
|
print(f"Searching for name: '{name}', dob: {dob}")
|
||
|
|
|
||
|
|
# Search for matching records in your info model
|
||
|
|
info_records = self.env['info.info'].search([
|
||
|
|
('name', '=ilike', name), # Case-insensitive match for name
|
||
|
|
('dob', '=', '08/02/2000') # Exact date match for DOB
|
||
|
|
])
|
||
|
|
|
||
|
|
# Debug: Print search results
|
||
|
|
print(f"Found {len(info_records)} matching records")
|
||
|
|
|
||
|
|
# Debug: Print found records
|
||
|
|
for record in info_records:
|
||
|
|
print(f"Found record - ID: {record.id}, Name: '{record.name}', DOB: {record.date_of_birth}")
|
||
|
|
|
||
|
|
if info_records:
|
||
|
|
# Update status to True and add tracking information
|
||
|
|
info_records.write({
|
||
|
|
'status': True,
|
||
|
|
'survey_processed': True,
|
||
|
|
'survey_id': self.survey_id.id,
|
||
|
|
'survey_input_id': survey_input.id,
|
||
|
|
'processed_date': fields.Datetime.now()
|
||
|
|
})
|
||
|
|
|
||
|
|
_logger.info(f"Updated {len(info_records)} records for {name} with DOB {dob}")
|
||
|
|
return len(info_records)
|
||
|
|
|
||
|
|
return 0
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
_logger.error(f"Database error while updating info model for {name}: {str(e)}")
|
||
|
|
raise Exception(f"Database error while updating: {str(e)}")
|
||
|
|
|
||
|
|
def reset_wizard(self):
|
||
|
|
"""
|
||
|
|
Reset wizard to initial state
|
||
|
|
"""
|
||
|
|
self.write({
|
||
|
|
'processed_count': 0,
|
||
|
|
'updated_records': 0,
|
||
|
|
'no_match_count': 0,
|
||
|
|
'error_count': 0,
|
||
|
|
'status': 'draft',
|
||
|
|
'details': False
|
||
|
|
})
|
||
|
|
return {
|
||
|
|
'type': 'ir.actions.act_window',
|
||
|
|
'res_model': 'survey.export.wizard',
|
||
|
|
'res_id': self.id,
|
||
|
|
'view_mode': 'form',
|
||
|
|
'target': 'new'
|
||
|
|
}
|