def execute_employee_organization_setup(self, organization_setup_data, do_validation=True):
        result = None

        # Do validation first, and short circuit if failed
        if (do_validation):
            result = self.validate_employee_organization_setup_data(organization_setup_data)
        else:
            # directly construct the result, skipping validation
            result = OperationResult(organization_setup_data)

        # If the operation input info is not valid to begin with
        # simply short circuit and return it
        if (result.has_issue()):
            raise Exception(
                "Encountered validation issues while executing employee organization setup!")

        # get employee profile to update
        employee_profile = organization_setup_data.get_employee_profile()

        # get manager's profile
        manager_profile = organization_setup_data.get_manager_profile()

        # now do the assignment
        employee_profile.manager = manager_profile
        employee_profile.save()

        result.set_output_data(organization_setup_data)
        return result
    def batch_validate_employee_organization_setup_data(self, organization_setup_data_list):
        result = OperationResult(organization_setup_data_list)

        if (not organization_setup_data_list):
            result.append_issue(
                'Did not find any employee organization setup to handle'
            )
        else:
            has_invalid = False
            validation_results = []

            for data in organization_setup_data_list:
                validate_result = self.validate_employee_organization_setup_data(data)
                if (validate_result.has_issue()):
                    has_invalid = True   

                validation_results.append(validate_result)

            if (has_invalid):
                result.append_issue(
                    'There are validation issues on some employee organization setup data.'
                )

            result.set_output_data(validation_results)

        return result
Exemple #3
0
    def validate_batch(self, account_creation_data_list):
        result = OperationResult(account_creation_data_list)

        if (not account_creation_data_list):
            result.append_issue('Did not find any account info to handle')
        else:
            # Also do some batch level validations
            exist_emails = []
            has_invalid = False
            account_validation_results = []

            # Collect all new account employee names
            employee_names = []
            for account_info in account_creation_data_list:
                full_name = account_info.first_name + account_info.last_name
                employee_names.append(full_name)

            for account_info in account_creation_data_list:
                account_result = self.validate(account_info)

                if account_info.email not in exist_emails:
                    exist_emails.append(account_info.email)
                else:
                    account_result.append_issue(
                        'The email specificed is also used on another account in this batch'
                    )

                # Check whether the account has manager info specified
                # and if so, check the validity of the manager info
                if (account_info.manager_first_name
                        and account_info.manager_last_name):
                    manager_full_name = account_info.manager_first_name + account_info.manager_last_name
                    if (manager_full_name not in employee_names):
                        # the specified manager name does not match any of the employees
                        account_result.append_issue(
                            'Could not locate an employee based on the manager information'
                        )

                if (account_result.has_issue()):
                    has_invalid = True

                account_validation_results.append(account_result)

            if (has_invalid):
                result.append_issue(
                    'There are validation issues on some account info.')

            result.set_output_data(account_validation_results)

        return result
    def terminate_employee(self, termination_data):
        result = OperationResult(termination_data)
        employee_profiles = EmployeeProfile.objects.filter(
            person=termination_data.person_id,
            company=termination_data.company_id)

        if (len(employee_profiles) <= 0):
            raise Exception(
                'Could not locate employee profile for person [%s]' %
                termination_data.person_id)

        employee_profile = employee_profiles[0]
        employee_profile.end_date = termination_data.end_date
        employee_profile.employment_status = EMPLOYMENT_STATUS_TERMINATED
        employee_profile.save()

        result.set_output_data(employee_profile)

        # Now send termination email
        self._send_termination_email(employee_profile)

        return result
    def parse_batch_employee_organization_import_raw_data(self, batch_import_raw_data):
        result = OperationResult(batch_import_raw_data)
        parsed_org_data_list = []

        # check all lines for number of fields
        # if found bad ones, send the main wrapper back without
        # construting the individual ones
        for line in batch_import_raw_data.raw_data.split('\n'):
            if (not line.strip()):
                continue

            tokens = line.split('\t')

            if (len(tokens) != len(self.REQUIRED_RAW_DATA_FIELDS)):
                result.append_issue(
                    'The line [%s] fails to parse properly. Reason: Do not have enough number of fields' % line
                )
            else:

                # parse the fields into domain object and 
                # construct the DTO needed
                org_data = {
                    'company_id': batch_import_raw_data.company_id,
                    'employee_first_name': self._get_field_value(tokens, self.FIELD_FIRST_NAME),
                    'employee_last_name': self._get_field_value(tokens, self.FIELD_LAST_NAME),
                    'manager_first_name': self._get_field_value(tokens, self.FIELD_MANAGER_FIRST_NAME),
                    'manager_last_name': self._get_field_value(tokens, self.FIELD_MANAGER_LAST_NAME)
                }

                # Parse the line into objects
                # Utilize serializers to perform all the details
                serializer = EmployeeOrganizationSetupDataPostSerializer(data=org_data)

                if (not serializer.is_valid()):
                    result.append_issue(
                        'The line [%s] fails to parse properly. Reasons:[%s]' % (line, serializer.errors)
                    )
                else:
                    parsed_org_data_list.append(serializer.object)

        # Do batch validation,
        #  - Collect batch level issues into the result
        #  - include the list of validated account data as output
        batch_validation_result = self.batch_validate_employee_organization_setup_data(parsed_org_data_list)
        batch_validation_result.copy_issues_to(result)
        result.set_output_data(batch_validation_result.output_data)

        return result
Exemple #6
0
    def parse_raw_data(self, batch_account_raw_data):
        result = OperationResult(batch_account_raw_data)
        parsed_account_data_list = []

        # check all lines for number of fields
        # if found bad ones, send the main wrapper back without
        # construting the individual ones
        for line in batch_account_raw_data.raw_data.split('\n'):
            if (not line.strip()):
                continue

            tokens = line.split('\t')

            if (len(tokens) != len(self.REQUIRED_RAW_DATA_FIELDS)):
                result.append_issue(
                    'The line [%s] fails to parse properly. Reason: Do not have enough number of fields'
                    % line)
            else:
                # try parsing some data first and log errors if found
                start_date = None
                try:
                    start_date = datetime.strptime(
                        self._get_field_value(tokens, self.FIELD_START_DATE),
                        '%m/%d/%Y')
                except:
                    result.append_issue(
                        'The line [%s] fails to parse properly. Reason: Failed to parse the given employment start date'
                        % (line))
                    continue

                benefit_start_date = None
                try:
                    benefit_start_date = datetime.strptime(
                        self._get_field_value(tokens,
                                              self.FIELD_BENEFIT_START_DATE),
                        '%m/%d/%Y')
                except:
                    result.append_issue(
                        'The line [%s] fails to parse properly. Reason: Failed to parse the given benefit start date'
                        % (line))
                    continue

                # Parse the line into objects
                # Utilize serializers to perform all the details
                compensation_data = {
                    'annual_base_salary':
                    self._get_field_value(tokens,
                                          self.FIELD_ANNUAL_BASE_SALARY),
                    'hourly_rate':
                    self._get_field_value(tokens, self.FIELD_HOURLY_RATE),
                    'projected_hour_per_month':
                    self._get_field_value(tokens,
                                          self.FIELD_PROJECTED_HOUR_PER_MONTH),
                    'effective_date':
                    start_date
                }

                account_data = {
                    'company_id':
                    batch_account_raw_data.company_id,
                    'first_name':
                    self._get_field_value(tokens, self.FIELD_FIRST_NAME),
                    'last_name':
                    self._get_field_value(tokens, self.FIELD_LAST_NAME),
                    'employment_type':
                    self._get_field_value(tokens, self.FIELD_EMPLOYMENT_TYPE),
                    'email':
                    self._get_field_value(tokens, self.FIELD_EMAIL),
                    'password':
                    self._get_field_value(tokens, self.FIELD_PASSWORD),
                    'employee_number':
                    self._get_field_value(tokens, self.FIELD_EMPLOYEE_NUMBER),
                    'company_user_type':
                    USER_TYPE_EMPLOYEE,
                    'send_email':
                    batch_account_raw_data.send_email,
                    'new_employee':
                    False,
                    'create_docs':
                    False,
                    'start_date':
                    start_date,
                    'benefit_start_date':
                    benefit_start_date,
                    'group_name':
                    self._get_field_value(tokens, self.FIELD_GROUP_NAME),
                    'compensation_info':
                    compensation_data,
                    'manager_first_name':
                    self._get_field_value(tokens,
                                          self.FIELD_MANAGER_FIRST_NAME),
                    'manager_last_name':
                    self._get_field_value(tokens,
                                          self.FIELD_MANAGER_LAST_NAME),
                    'doc_fields': []
                }

                serializer = AccountCreationDataSerializer(data=account_data)

                if (not serializer.is_valid()):
                    result.append_issue(
                        'The line [%s] fails to parse properly. Reasons:[%s]' %
                        (line, serializer.errors))
                else:
                    parsed_account_data_list.append(serializer.object)

        # Do batch validation,
        #  - Collect batch level issues into the result
        #  - include the list of validated account data as output
        batch_validation_result = self.validate_batch(parsed_account_data_list)
        batch_validation_result.copy_issues_to(result)
        result.set_output_data(batch_validation_result.output_data)

        return result
Exemple #7
0
    def execute_creation(self, account_info, do_validation=True):
        result = OperationResult(account_info)
        account_result = None

        # Do validation first, and short circuit if failed
        if (do_validation):
            account_result = self.validate(account_info)
        else:
            # directly construct the result, skipping validation
            account_result = OperationResult(account_info)

        # If the account creation info is not valid to begin with
        # simply short circuit and return it
        if (account_result.has_issue()):
            return account_result

        userManager = AuthUserManager()

        # Create the actual user data
        password = settings.DEFAULT_USER_PW
        if account_info.password:
            password = account_info.password
        user = User.objects.create_user(account_info.email, password)
        user.first_name = account_info.first_name
        user.last_name = account_info.last_name
        user.save()

        # Create the company_user data
        company_user = CompanyUser(
            company_id=account_info.company_id,
            user=user,
            company_user_type=account_info.company_user_type)

        if account_info.new_employee is not None:
            company_user.new_employee = account_info.new_employee

        company_user.save()

        # Now create the person object
        person_data = {
            'first_name': account_info.first_name,
            'last_name': account_info.last_name,
            'user': user.id,
            'relationship': SELF,
            'person_type': 'primary_contact',
            'email': user.email
        }

        person_serializer = PersonSimpleSerializer(data=person_data)
        if person_serializer.is_valid():
            person_serializer.save()
        else:
            raise Exception("Failed to create person record")

        # Create the employee profile
        key_service = HashKeyService()
        person_id = key_service.decode_key(person_serializer.data['id'])
        pin = account_info.pin
        pinService = EmployeePinService()
        if not pin:
            pin = pinService.get_company_wide_unique_pin(
                account_info.company_id, user.id)

        profile_data = {
            'person': person_id,
            'company': account_info.company_id,
            'start_date': account_info.start_date,
            'benefit_start_date': account_info.benefit_start_date,
            'pin': pin
        }

        if (account_info.compensation_info.annual_base_salary is not None):
            profile_data[
                'annual_base_salary'] = account_info.compensation_info.annual_base_salary

        if (account_info.employment_type):
            profile_data['employment_type'] = account_info.employment_type

        if (account_info.manager_id):
            profile_data['manager'] = account_info.manager_id

        if (account_info.employee_number):
            profile_data['employee_number'] = account_info.employee_number

        profile_serializer = EmployeeProfilePostSerializer(data=profile_data)

        if profile_serializer.is_valid():
            profile_serializer.save()
        else:
            raise Exception("Failed to create employee profile record")

        # Now check to see send email and create documents
        if company_user.company_user_type == 'employee':
            if account_info.send_email:
                # now try to create the onboard email for this user.
                try:
                    onboard_email(
                        "%s %s" % (user.first_name, user.last_name),
                        account_info.company_id,
                        [account_info.email, settings.SUPPORT_EMAIL_ADDRESS],
                        user.id)
                except StandardError:
                    raise Exception("Failed to send email to employee")

            if (account_info.create_docs):

                # Let's create the documents for this new user
                try:
                    doc_gen = UserDocumentGenerator(company_user.company, user)
                    doc_gen.generate_all_document(account_info.doc_fields)
                except Exception:
                    raise Exception(
                        "Failed to generate documents for employee")

            # Create the initial compensation record
            compensation_data = {
                'person': person_id,
                'company': account_info.company_id,
                'annual_base_salary':
                account_info.compensation_info.annual_base_salary,
                'projected_hour_per_month':
                account_info.compensation_info.projected_hour_per_month,
                'hourly_rate': account_info.compensation_info.hourly_rate,
                'effective_date':
                account_info.compensation_info.effective_date,
                'increase_percentage': None
            }

            compensation_serializer = EmployeeCompensationPostSerializer(
                data=compensation_data)

            if (compensation_serializer.is_valid()):
                compensation_serializer.save()
            else:
                raise Exception("Failed to create compensation record")

            if account_info.group_id:
                self._add_to_group(account_info.group_id, user.id)

            elif account_info.group_name:
                group_id = self._get_or_create_group(account_info.group_name,
                                                     account_info.company_id)
                if group_id:
                    self._add_to_group(group_id, user.id)
                else:
                    raise Exception(
                        "Cannot get group_id from group name {}".format(
                            account_info.group_name))

            account_info.user_id = user.id

            account_result.set_output_data(account_info)

            # Now for the new employee being created, setup any information
            # required for external parties (such as payroll and benefit service)
            # providers.
            self.company_integration_provider_data_service.generate_and_record_external_employee_number(
                user.id)

        return account_result
Exemple #8
0
    def validate(self, account_info):
        result = OperationResult(account_info)

        if (not account_info or not account_info.email
                or not account_info.company_id
                or not account_info.company_user_type
                or not account_info.first_name or not account_info.last_name
                or not account_info.compensation_info):
            result.append_issue(
                "Missing necessary information for account creation")
        account_info.email = account_info.email

        if (account_info.send_email and account_info.password):
            result.append_issue(
                "Password should not be specified if the system is to send registration email"
            )

        if (not account_info.send_email):
            if (not account_info.password):
                result.append_issue(
                    "Password must be specified if the system is instructed to not send registration email"
                )
            elif (len(account_info.password) < 8):
                result.append_issue(
                    "Password must be no shorter than 8 characters")

        try:
            Company.objects.get(pk=account_info.company_id)
        except Company.DoesNotExist:
            result.append_issue("Specificed company does not exist")

        company_users = CompanyUser.objects.filter(
            company=account_info.company_id)

        for c in company_users:
            if (c.company_user_type == account_info.company_user_type
                    and c.user.email == account_info.email):
                result.append_issue("Specified email has already been used")

        if (not account_info.send_email and not account_info.password):
            result.append_issue("Missing initial password for the new account")

        # Now validate the initial compensation record
        if (account_info.employment_type
                in [PART_TIME, CONTRACTOR, INTERN, PER_DIEM]):
            if (not account_info.compensation_info.hourly_rate or
                    not account_info.compensation_info.projected_hour_per_month
                ):
                result.append_issue("Compensation record info is incomplete")
        elif (account_info.employment_type == FULL_TIME):
            # Full time employee could be on hourly payroll
            if (not account_info.compensation_info.annual_base_salary and
                (not account_info.compensation_info.hourly_rate or
                 not account_info.compensation_info.projected_hour_per_month)):
                result.append_issue("Compensation record info is incomplete")
        else:
            result.append_issue(
                'The specified employment type [%s] is not valid.' %
                account_info.employment_type)

        if not account_info.group_name and not account_info.group_id:
            result.append_issue('Company group not specified.')

        # if manager profile id is provided, validate its existence
        if (account_info.manager_id):
            try:
                EmployeeProfile.objects.get(pk=account_info.manager_id)
            except EmployeeProfile.DoesNotExist:
                result.append_issue(
                    'Could not find employee profile based on the manager info provided.'
                )

        result.set_output_data(account_info)

        return result
    def validate_employee_organization_setup_data(self, organization_setup_data):
        result = OperationResult(organization_setup_data)
        result.set_output_data(organization_setup_data)

        if (not organization_setup_data or
            not organization_setup_data.company_id):
            result.append_issue(
                "Missing necessary information for employee organization setup"
            )
            return result

        if (not organization_setup_data.employee_person_id):
            result.append_issue(
                "Could not locate employee profile for the given employee"
            )

        # It is a valid case where manager info is not specified, which 
        # we infer as to not-setup or remove manager for the employee
        # But it is invalid that the manager info is specified but failed
        # to resolve to a valid employee profile
        if (organization_setup_data.has_manager_info_specified 
            and not organization_setup_data.manager_profile_id):
            result.append_issue(
                "Could not locate manager's employee profile based on info provided"
            )

        # check the employee and manager belong to the same company
        employee_profile = organization_setup_data.get_employee_profile()
        manager_profile = organization_setup_data.get_manager_profile()
        if (employee_profile and manager_profile):
            if (employee_profile.company.id != manager_profile.company.id):
                result.append_issue(
                    "The employee and manager specified do not work in the same company"
                )

        return result