def add_membership_payment_record(self, ctx, membership: Membership, free: bool): LOG.debug("membership_add_membership_payment_record", extra=log_extra(ctx, duration=membership.duration, membership_accoun=membership.account)) if free and not Roles.TRESO_WRITE.value in ctx.get(CTX_ROLES): raise UnauthorizedError( "Impossibilité de faire une cotisation gratuite") payment_method = self.payment_method_repository.get_by_id( ctx, membership.payment_method) asso_account, _ = self.account_repository.search_by( ctx, limit=1, filter_=AbstractAccount( name=KnownAccountExpense.ASSOCIATION_EXPENCE.value)) if len(asso_account) != 1: raise AccountNotFoundError( KnownAccountExpense.ASSOCIATION_EXPENCE.value) tech_account, _ = self.account_repository.search_by( ctx, limit=1, filter_=AbstractAccount( name=KnownAccountExpense.TECHNICAL_EXPENSE.value)) if len(tech_account) != 1: raise AccountNotFoundError( KnownAccountExpense.TECHNICAL_EXPENSE.value) src_account = self.account_repository.get_by_id( ctx, membership.account) price = self.duration_price[membership.duration] # Expressed in EUR. if price == 50 and not membership.has_room: price = 9 duration_str = self.duration_string.get(membership.duration) title = f'Internet - {duration_str}' self.transaction_repository.create( ctx, AbstractTransaction(value=9 if not free else 0, src=src_account.id, dst=asso_account[0].id, name=title + " (gratuit)" if free else title, payment_method=payment_method.id)) if price > 9 and not free: self.transaction_repository.create( ctx, AbstractTransaction(value=price - 9, src=src_account.id, dst=tech_account[0].id, name=title, payment_method=payment_method.id))
def test_unknown_account( self, ctx, mock_membership_repository: MembershipRepository, mock_member_repository: MemberRepository, mock_account_repository: AccountRepository, sample_member: Member, mock_charter_repository: CharterRepository, sample_subscription_duration_account_payment_method: SubscriptionBody, sample_membership_pending_rules: Membership, member_manager: MemberManager): mock_member_repository.get_by_id = MagicMock( return_value=(sample_member)) mock_membership_repository.search = MagicMock( return_value=([sample_membership_pending_rules], 1)) mock_account_repository.get_by_id = MagicMock( return_value=(None), side_effect=AccountNotFoundError("")) mock_charter_repository.get = MagicMock( return_value=str(datetime.datetime.today())) with raises(AccountNotFoundError): member_manager.update_subscription( ctx, sample_member.id, sample_subscription_duration_account_payment_method) mock_membership_repository.search.assert_called_once() mock_member_repository.get_by_id.assert_called_once() mock_account_repository.get_by_id.assert_called_once() mock_charter_repository.get.assert_called_once() mock_membership_repository.update.assert_not_called()
def create(self, ctx, abstract_transaction: AbstractTransaction) -> object: session: Session = ctx.get(CTX_SQL_SESSION) now = datetime.now() admin_id = ctx.get(CTX_ADMIN) account_src = None if abstract_transaction.src is not None: account_src = session.query(Account).filter( Account.id == abstract_transaction.src).one_or_none() if not account_src: raise AccountNotFoundError(abstract_transaction.src) account_dst = None if abstract_transaction.dst is not None: account_dst = session.query(Account).filter( Account.id == abstract_transaction.dst).one_or_none() if not account_dst: raise AccountNotFoundError(abstract_transaction.dst) method = None if abstract_transaction.payment_method is not None: method = session.query(PaymentMethod).filter( PaymentMethod.id == abstract_transaction.payment_method).one_or_none() if not method: raise PaymentMethodNotFoundError( abstract_transaction.payment_method) transaction = SQLTransaction( src=account_src.id if account_src else None, dst=account_dst.id if account_dst else None, value=abstract_transaction.value, name=abstract_transaction.name, timestamp=now, attachments="", type=method.id if method else None, author_id=admin_id, pending_validation=abstract_transaction.pending_validation if abstract_transaction.pending_validation else False) with track_modifications(ctx, session, transaction): session.add(transaction) session.flush() return _map_transaction_sql_to_entity(transaction)
def buy(self, ctx, member_id: int, payment_method_id: int, product_ids: List[int] = []) -> None: if not product_ids: raise ProductNotFoundError("None") payment_method = self.payment_method_repository.get_by_id(ctx, payment_method_id) dst_accounts, _ = self.account_repository.search_by(ctx, limit=1, filter_=AbstractAccount(name=KnownAccountExpense.TECHNICAL_EXPENSE.value)) if not dst_accounts: raise AccountNotFoundError(KnownAccountExpense.TECHNICAL_EXPENSE.value) src_accounts, _ = self.account_repository.search_by(ctx, limit=1, filter_=AbstractAccount(member=member_id)) if not src_accounts: raise AccountNotFoundError(KnownAccountExpense.TECHNICAL_EXPENSE.value) for i in product_ids: product = self.product_repository.get_by_id(ctx, i) _ = self.transaction_repository.create( ctx, AbstractTransaction( src=src_accounts[0].id, dst=dst_accounts[0].id, name=product.name, value=product.selling_price, payment_method=payment_method.id, ))
def test_unknown_account( self, ctx, mock_membership_repository: MembershipRepository, mock_member_repository: MemberRepository, mock_account_repository: AccountRepository, sample_member: Member, mock_charter_repository: CharterRepository, sample_subscription_duration_account_payment_method: SubscriptionBody, member_manager: MemberManager): mock_member_repository.get_by_id = MagicMock( return_value=(sample_member)) mock_membership_repository.search = MagicMock(return_value=([], 0)) mock_account_repository.get_by_id = MagicMock( return_value=(None), side_effect=AccountNotFoundError("")) mock_charter_repository.get = MagicMock( return_value=str(datetime.datetime.today())) with raises(AccountNotFoundError): member_manager.create_subscription( ctx, sample_member.id, sample_subscription_duration_account_payment_method)
def test_no_src_account( self, ctx, mock_payment_method_repository: PaymentMethodRepository, mock_account_repository: AccountRepository, member_manager: MemberManager, sample_membership_empty: Membership, sample_account1: Account, sample_payment_method: PaymentMethod): mock_payment_method_repository.get_by_id = MagicMock( return_value=(sample_payment_method) ) # in this test don't care of the return value, the most important thing is that the function does not raise NotFound exception mock_account_repository.search_by = MagicMock( side_effect=[([sample_account1], 0), ([sample_account1], 0)]) mock_account_repository.get_by_id = MagicMock( side_effect=AccountNotFoundError("")) with raises(AccountNotFoundError): member_manager.add_membership_payment_record( ctx, sample_membership_empty, False) mock_payment_method_repository.get_by_id.assert_called_once() mock_account_repository.search_by.assert_called() mock_account_repository.get_by_id.assert_called_once()
def create(self, ctx, abstract_account: Account) -> object: session: Session = ctx.get(CTX_SQL_SESSION) LOG.debug("sql_account_repository_create_called", extra=log_extra(ctx, account_type=abstract_account.account_type)) now = datetime.now() account_type_query = session.query(AccountType) if abstract_account.account_type is not None: LOG.debug("sql_account_repository_search_account_type", extra=log_extra(ctx, account_type=abstract_account.account_type)) account_type_query = account_type_query.filter(AccountType.id == abstract_account.account_type) else: account_type_query = account_type_query.filter(AccountType.name == "Adherent") account_type = account_type_query.one_or_none() if account_type is None: raise AccountNotFoundError(abstract_account.account_type) adherent = None if abstract_account.member is not None: adherent = session.query(Adherent).filter(Adherent.id == abstract_account.member).one_or_none() if not adherent: raise MemberNotFoundError(abstract_account.member) account = SQLAccount( name=abstract_account.name, actif=abstract_account.actif, type=account_type.id, creation_date=now, compte_courant=abstract_account.compte_courant, pinned=abstract_account.pinned, adherent_id=adherent.id if adherent else None ) with track_modifications(ctx, session, account): session.add(account) session.flush() LOG.debug("sql_account_repository_create_finished", extra=log_extra(ctx, account_id=account.id)) return _map_account_sql_to_entity(account)
def update_subscription(self, ctx, member_id: int, body: SubscriptionBody) -> None: member = self.member_repository.get_by_id(ctx, member_id) if not member: raise MemberNotFoundError(member_id) subscription = self.latest_subscription(ctx=ctx, member_id=member_id) if not subscription: raise MembershipNotFoundError() if subscription.status in [ MembershipStatus.COMPLETE, MembershipStatus.CANCELLED, MembershipStatus.ABORTED ]: raise MembershipStatusNotAllowed( subscription.status, "membership already completed, cancelled or aborted") state = MembershipStatus(subscription.status) if state == MembershipStatus.PENDING_RULES: date_signed_minet = self.charter_repository.get( ctx, member_id=member_id, charter_id=1) if date_signed_minet is not None and date_signed_minet != "": LOG.debug( "create_membership_record_switch_status_to_pending_payment_initial" ) state = MembershipStatus.PENDING_PAYMENT_INITIAL else: raise CharterNotSigned(str(member_id)) if body.duration is not None and body.duration != 0: if body.duration not in self.duration_price: LOG.warning("create_membership_record_no_price_defined", extra=log_extra(ctx, duration=body.duration)) raise NoPriceAssignedToThatDuration(body.duration) if state == MembershipStatus.PENDING_PAYMENT_INITIAL: if body.duration is not None: LOG.debug( "create_membership_record_switch_status_to_pending_payment" ) state = MembershipStatus.PENDING_PAYMENT if body.account is not None: account = self.account_repository.get_by_id(ctx, body.account) if not account: raise AccountNotFoundError(body.account) if body.payment_method is not None: payment_method = self.payment_method_repository.get_by_id( ctx, body.payment_method) if not payment_method: raise PaymentMethodNotFoundError(body.payment_method) if state == MembershipStatus.PENDING_PAYMENT: if body.account is not None and body.payment_method is not None: LOG.debug( "create_membership_record_switch_status_to_pending_payment_validation" ) state = MembershipStatus.PENDING_PAYMENT_VALIDATION try: self.membership_repository.update(ctx, subscription.uuid, body, state) except Exception: raise
def create_subscription(self, ctx, member_id: int, body: SubscriptionBody) -> Membership: """ Core use case of ADH. Registers a membership. User story: As an admin, I can create a new membership record, so that a member can have internet access. :param ctx: context :param member_id: member_id :param membership: entity AbstractMembership :raise IntMustBePositiveException :raise NoPriceAssignedToThatDurationException :raise MemberNotFound :raise UnknownPaymentMethod """ member = self.member_repository.get_by_id(ctx, member_id) if not member: raise MemberNotFoundError(member_id) latest_subscription = self.latest_subscription(ctx=ctx, member_id=member_id) if latest_subscription and latest_subscription.status not in [ MembershipStatus.COMPLETE.value, MembershipStatus.CANCELLED.value, MembershipStatus.ABORTED.value ]: raise MembershipAlreadyExist(latest_subscription.status) state = MembershipStatus.PENDING_RULES if state == MembershipStatus.PENDING_RULES: date_signed_minet = self.charter_repository.get( ctx, member_id=member_id, charter_id=1) if date_signed_minet is not None and date_signed_minet != "": LOG.debug( "create_membership_record_switch_status_to_pending_payment_initial" ) state = MembershipStatus.PENDING_PAYMENT_INITIAL if state == MembershipStatus.PENDING_PAYMENT_INITIAL: if body.duration is not None and body.duration != 0: if body.duration not in self.duration_price: LOG.warning("create_membership_record_no_price_defined", extra=log_extra(ctx, duration=body.duration)) raise NoPriceAssignedToThatDuration(body.duration) LOG.debug( "create_membership_record_switch_status_to_pending_payment" ) state = MembershipStatus.PENDING_PAYMENT if state == MembershipStatus.PENDING_PAYMENT: if body.account is not None and body.payment_method is not None: account = self.account_repository.get_by_id(ctx, body.account) if not account: raise AccountNotFoundError(body.account) payment_method = self.payment_method_repository.get_by_id( ctx, body.payment_method) if not payment_method: raise PaymentMethodNotFoundError(body.payment_method) LOG.debug( "create_membership_record_switch_status_to_pending_payment_validation" ) state = MembershipStatus.PENDING_PAYMENT_VALIDATION try: membership_created = self.membership_repository.create( ctx, body, state) except UnknownPaymentMethod: LOG.warning("create_membership_record_unknown_payment_method", extra=log_extra(ctx, payment_method=body.payment_method)) raise LOG.info("create_membership_record", extra=log_extra(ctx, membership_uuis=membership_created.uuid, membership_status=membership_created.status)) return membership_created