"""Contract Term Conditions logic.""" from abacus_common_logic.constants.error import ERROR_ENTITY_DOES_NOT_EXIST from owsresponse import response from abacus_contract import models from abacus_contract.constants.error import ( ERROR_CANNOT_DELETE_CONTRACT_TERM_CONDITION, ERROR_INVALID_RELATIONSHIP, ) from abacus_contract.schemas.contract_term_condition import ContractTermConditionSchema from abacus_contract.utils.format_error import validation_error def create_contract_term_conditions(contract_term_id: int, params: list): """Create contract terms conditions logic.""" models.ContractTerm.get_by_id_or_error(contract_term_id) new_conditions = list() for item in params: term_rate = item.get('term_rate') commission = item.get('commission') if term_rate is not None and commission is None: commission = 100 - term_rate if commission is not None and term_rate is None: term_rate = 100 - commission new_condition = models.ContractTermCondition.build( contract_term_id=contract_term_id, conditions=item['conditions'], priority=item['priority'], term_rate=term_rate, commission=commission, contract_term_condition_name=item.get('contract_term_condition_name'), ) new_conditions.append(new_condition) models.ContractTermCondition.commit_changes() message = ContractTermConditionSchema(many=True).dump(new_conditions) return response.Response(message=message, status=201) def get_conditions_by_term_id(contract_term_id): """Get conditions by contract terms.""" models.ContractTerm.get_by_id_or_error(contract_term_id) result = models.ContractTermCondition.get_active_term_conditions_with_order_by( contract_term_id ) message = ContractTermConditionSchema(many=True).dump(result) return response.Response(message=message, status=200) def get_condition_records_by_term_ids(authorized_term_ids: list) -> list: """Serialize active conditions for the given authorized term ids as flat records. Each record carries contract_term_id; the caller groups and shapes them into the dataload response. """ if not authorized_term_ids: return [] conditions = models.ContractTermCondition.get_active_term_conditions_by_term_ids( authorized_term_ids ) return ContractTermConditionSchema(many=True).dump(conditions) def soft_delete_contract_term_conditions(term_condition_ids: list): """Soft delete specified contract_term_conditions.""" term_conditions_to_be_deleted = models.ContractTermCondition.get_all_by_id( term_condition_ids ) unique_contract_term_ids = list( set([condition.contract_term_id for condition in term_conditions_to_be_deleted]) ) deletion_error = _validate_soft_deletion( term_conditions_to_be_deleted, term_condition_ids, unique_contract_term_ids ) if deletion_error is not None: return deletion_error for contract_term_condition in term_conditions_to_be_deleted: contract_term_condition._soft_delete() _reprioritize(unique_contract_term_ids) models.ContractTermCondition.commit_changes() return response.Response(message='ok', status=200) def update_contract_term_conditions(contract_term_id: int, update_params: list): """Update contract_term_conditions data.""" contract_term = models.ContractTerm.get_by_id_or_error(contract_term_id) error = None for condition in update_params: contract_term_condition_id = condition.get('contract_term_condition_id') contract_term_condition = models.ContractTermCondition.get_by_id_or_error( contract_term_condition_id ) term_rate = condition.get('term_rate') commission = condition.get('commission') contract_term_condition_name = condition.get('contract_term_condition_name') if term_rate is not None and commission is None: commission = 100 - term_rate if commission is not None and term_rate is None: term_rate = 100 - commission if term_rate or commission: condition.update({'term_rate': term_rate, 'commission': commission}) if contract_term_condition_name: condition['contract_term_condition_name'] = contract_term_condition_name if not contract_term_condition.contract_term == contract_term: error = validation_error( ERROR_INVALID_RELATIONSHIP.format( child='contract_term_condition', child_id=contract_term_condition_id, parent='contract_term', parent_id=contract_term_id, ) ) break contract_term_condition.update_attributes(**condition) if error is not None: return error models.ContractTermCondition.commit_changes() message = ContractTermConditionSchema(many=True).dump(contract_term.conditions) return response.Response(message=message, status=200) def _reprioritize(contract_term_ids: list): """Update contract term condition priorities after deletion.""" for contract_term_id in contract_term_ids: conditions = ( models.ContractTermCondition.get_active_term_conditions_with_order_by( contract_term_id ) ) priority = 1 for condition in conditions: condition.priority = priority priority += 1 def _validate_soft_deletion( conditions_to_be_deleted: list, contract_term_condition_ids: list, contract_term_ids: list, ): """Validate each contract term will have at least one term condition.""" if not len(conditions_to_be_deleted) == len(contract_term_condition_ids): return validation_error( ERROR_ENTITY_DOES_NOT_EXIST.format( object_type=models.ContractTermCondition.get_class_name(), object_id='' ) ) term_condition_map = {} for condition in conditions_to_be_deleted: contract_term_id = condition.contract_term_id if contract_term_id in term_condition_map: term_condition_map[contract_term_id].append(condition) else: term_condition_map[contract_term_id] = [condition] for contract_term_id in contract_term_ids: active_conditions = models.ContractTermCondition.get_active_term_conditions( contract_term_id ).all() if len(active_conditions) in [1, len(term_condition_map[contract_term_id])]: return validation_error(ERROR_CANNOT_DELETE_CONTRACT_TERM_CONDITION)