"""Accounting Period logic.""" from abacus_common_logic.utils.dates import current_timestamp from owsresponse import response from royalties import models from royalties.constants import constants, error from royalties.logic.statement_period import _validate_statement_period_state from royalties.schemas.accounting_period import AccountingPeriodDetailSchema from royalties.utils.format_error import validation_error accounting_period_detail_schema = AccountingPeriodDetailSchema() def create_accounting_period(**params): """Create an accounting period.""" accounting_period_name = params.get('accounting_period_name') statement_period_id = params.get('statement_period_id') contract_type = params.get('contract_type') try: _validate_statement_period_state(statement_period_id) _validate_accounting_period( accounting_period_name, contract_type, statement_period_id ) except Exception as e: return validation_error(str(e)) run_controllers = models.RunController.get_all_associated_to_contracts( contract_type ) new_acct_period = models.AccountingPeriod.create( accounting_period_name=accounting_period_name, accounting_runs=[ models.AccountingRun.build(run_controller=controller) for controller in run_controllers ], accounting_period_status=constants.ACCOUNTING_PERIOD_STATUSES.OPEN, contract_type=contract_type, statement_period_id=statement_period_id, ) return response.Response( message=accounting_period_detail_schema.dump(new_acct_period), status=201 ) def get_accounting_period_by_accounting_run(accounting_run_id): """Get accounting_period from accounting_run.accounting_period_id.""" accounting_run = models.AccountingRun.get_by_id_or_error( accounting_run_id, error_status=404 ) return response.Response( message=accounting_period_detail_schema.dump(accounting_run.accounting_period), status=200, ) def update_accounting_period(accounting_period, **params): """Update accounting period.""" new_name = params.get('accounting_period_name') new_acc_period_status = params.get('accounting_period_status') if new_acc_period_status and not accounting_period.is_new_acc_period_status_valid( new_acc_period_status ): return validation_error( error.ERROR_INVALID_PERIOD_STATUS.format( current_status=accounting_period.accounting_period_status, new_status=new_acc_period_status, ) ) if ( new_name and accounting_period.accounting_period_name != new_name and models.AccountingPeriod.find_by_name(new_name) ): return response.create_error_response( code='error', message=error.ERROR_ALREADY_EXISTS.format(object_type='Accounting Period'), status=400, ) if new_acc_period_status == constants.ACCOUNTING_PERIOD_STATUSES.CLOSED: params['closed_date'] = current_timestamp() accounting_period.update_attributes(**params) models.AccountingPeriod.commit_changes() return response.Response( message=accounting_period_detail_schema.dump(accounting_period), status=201 ) def validate_accounting_period_state(period_id): """Validate the period is open and accepting.""" period = models.AccountingPeriod.get_by_id(period_id) if not period: return error.ERROR_ENTITY_DOES_NOT_EXIST.format( object_type='AccountingPeriod', object_id=period_id ) if period.accounting_period_status == constants.ACCOUNTING_PERIOD_STATUSES.CLOSED: return error.ERROR_NO_OPEN_PERIOD def _validate_accounting_period( accounting_period_name, contract_type, statement_period_id ): """Validate accounting period.""" accounting_period = models.AccountingPeriod.get_current_period( statement_period_id, contract_type ) if accounting_period: raise Exception( error.ERROR_OPEN_PERIOD_EXISTS.format( contract_type=contract_type, statement_period_id=statement_period_id ) ) if models.AccountingPeriod.find_by_name(accounting_period_name): raise Exception( error.ERROR_ALREADY_EXISTS.format(object_type='Accounting Period') )