# -*- 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' }