def test_add_years(): """Test adding years to a date.""" initial_date = datetime.now() one_year_later = add_years(initial_date, 1) assert initial_date.year == one_year_later.year - 1 initial_date = datetime.strptime('2020-02-29', '%Y-%m-%d') tow_years_later = add_years(initial_date, 2) four_years_later = add_years(initial_date, 4) assert tow_years_later.month == 3 and tow_years_later.day == 1 assert four_years_later.month == initial_date.month and \ four_years_later.day == initial_date.day
def test_clear_and_renew_subscription(patron_type_grown_sion, patron_sion_no_email): """Test the `task patrons.tasks.clear_and_renew_subscription`.""" patron_sion = patron_sion_no_email # To test correctly all the code we need to disconnect the listener # `create_subscription_patron_transaction` method. Otherwise, the # first part of the task (clean_obsolete_subscriptions) will automatically # create new subscriptions because the last instruction is a # `patron.update()` call. after_record_update.disconnect(create_subscription_patron_transaction) # first step : clear all subscription for the patron and crate an new # obsolete subscription. if 'subscriptions' in patron_sion_no_email.get('patron', {}): del patron_sion_no_email['patron']['subscriptions'] start = datetime.now() - timedelta(days=200) end = start + timedelta(days=100) patron_sion.add_subscription(patron_type_grown_sion, start, end) assert len(patron_sion.get('patron', {}).get('subscriptions', [])) == 1 assert patron_sion.get('patron', {})['subscriptions'][0]['end_date'] == \ end.strftime('%Y-%m-%d') # clean old subscription - Reload the patron and check they are no more # subscriptions clean_obsolete_subscriptions() patron_sion = Patron.get_record_by_pid(patron_sion.pid) assert len(patron_sion.get('patron', {}).get('subscriptions', [])) == 0 # check for patron needed subscriptions and create new subscription if # needed. As our patron has no subscription and is still connected to # a patron type requiring subscription, this task should create a # new subscription for this patron check_patron_types_and_add_subscriptions() patron_sion = Patron.get_record_by_pid(patron_sion.pid) assert len(patron_sion.get('patron', {}).get('subscriptions', [])) == 1 assert patron_sion.get('patron', {})['subscriptions'][0]['end_date'] == \ add_years(datetime.now(), 1).strftime('%Y-%m-%d') # run both operation using task_clear_and_renew_subscriptions` and check # the result. The patron should still have one subscription but end_date # must be today. del patron_sion['patron']['subscriptions'] start = datetime.now() - timedelta(days=200) end = start + timedelta(days=100) patron_sion.add_subscription(patron_type_grown_sion, start, end) task_clear_and_renew_subscriptions() patron_sion = Patron.get_record_by_pid(patron_sion.pid) assert len(patron_sion.get('patron', {}).get('subscriptions', [])) == 1 assert patron_sion.get('patron', {})['subscriptions'][0]['end_date'] != \ end.strftime('%Y-%m-%d') # as we disconnect the `create_subscription_patron_transaction` listener # at the beginning, we need to connect it now. after_record_update.connect(create_subscription_patron_transaction)
def list_closed_dates(library_pid): """HTTP GET request to get the closed dates for a given library pid. USAGE : /api/libraries/<pid>/closed_dates?from=<from>&until=<until> optional parameters: * from: the lower interval date limit as 'YYYY-MM-DD' format. default value are sysdate - 1 month * until: the upper interval date limit as 'YYYY-MM-DD' format. default value are sysdate + 1 year :param library_pid: the library pid to search. """ library = Library.get_record_by_pid(library_pid) if not library: abort(404) # get start date from 'from' parameter from query string request start_date = request.args.get('from', datetime.now() - timedelta(days=31)) if isinstance(start_date, str): start_date = date_string_to_utc(start_date) start_date = start_date.replace(tzinfo=library.get_timezone()) # get end date from 'until' parameter from query string request end_date = request.args.get('until', add_years(datetime.now(), 1)) if isinstance(end_date, str): end_date = date_string_to_utc(end_date) end_date = end_date.replace(tzinfo=library.get_timezone()) delta = end_date - start_date # compute closed date closed_date = [] for i in range(delta.days + 1): tmp_date = start_date + timedelta(days=i) if not library.is_open(date=tmp_date, day_only=True): closed_date.append(tmp_date.strftime('%Y-%m-%d')) return jsonify({ 'params': { 'from': start_date.strftime('%Y-%m-%d'), 'until': end_date.strftime('%Y-%m-%d') }, 'closed_dates': closed_date })
def test_patron_subscription_transaction(patron_type_youngsters_sion, patron_sion_no_email): """Test the creation of a subscription transaction for a patron.""" subscription_start_date = datetime.now() subscription_end_date = add_years(subscription_start_date, 1) assert subscription_end_date.year == subscription_start_date.year + 1 assert subscription_end_date.month == subscription_start_date.month assert subscription_end_date.day == subscription_start_date.day subscription = PatronTransaction.create_subscription_for_patron( patron_sion_no_email, patron_type_youngsters_sion, subscription_start_date, subscription_end_date, dbcommit=True, reindex=True, delete_pid=True) assert subscription.get_number_of_patron_transaction_events() == 1 event = list(subscription.events)[0] assert event.get('type') == 'fee' assert event.get('subtype') == 'other' assert event.get('amount') == subscription.get('total_amount')
def check_patron_types_and_add_subscriptions(): """Check patron types with subscription amount and add subscriptions. Search for patron_type requiring a subscription. For each patron_type search about patron linked to it and without valid subscription. For each of these patrons, create a new subscription if needed. """ # Note this function should never doing anything because never any patron # linked to these patron types shouldn't have no subscription. This is # because, a listener creating an active subscription is linked to signal # create/update for any patron. In addition, the method # `clean_obsolete_subscriptions`, at the last loop instruction will update # the patron ; this update will trigger the same listener and so create a # new active subscription is necessary. for ptty in PatronType.get_yearly_subscription_patron_types(): patron_no_subsc = Patron.get_patrons_without_subscription(ptty.pid) for patron in patron_no_subsc: msg = 'Add a subscription for patron#{ptrn} ... it shouldn\'t ' \ 'happen !!'.format(ptrn=patron.pid) current_app.logger.error(msg) start_date = datetime.now() end_date = add_years(start_date, 1) patron.add_subscription(ptty, start_date, end_date)
def test_patron_subscription_transaction( patron_type_youngsters_sion, patron_sion): """Test the creation of a subscription transaction for a patron.""" subscription_start_date = datetime.now() subscription_end_date = add_years(subscription_start_date, 1) assert subscription_end_date.year == subscription_start_date.year + 1 assert subscription_end_date.month == subscription_start_date.month assert subscription_end_date.day == subscription_start_date.day subscription = create_subscription_for_patron( patron_sion, patron_type_youngsters_sion, subscription_start_date, subscription_end_date, dbcommit=True, reindex=True, delete_pid=True ) assert subscription.get_links_to_me() == {'events': 1} assert subscription.get_links_to_me(get_pids=True) == {'events': ['9']} event = list(subscription.events)[0] assert event.get('type') == 'fee' assert event.get('subtype') == 'other' assert event.get('amount') == subscription.get('total_amount')