def determine_carts_linked(session, cart_ids): """ Determines if all orders in relevant cart have corresponding Sierra order and bib number and updates cart linked status args: cart_ids: list of cart_ids that had their orders updated with oid """ mlogger.debug('Updating carts linked status.') # determine time period when wlos were assigned for cart_id in cart_ids: cart_rec = retrieve_record(session, Cart, did=cart_id) # check if all orders have oid if cart_rec: linked = True for o in cart_rec.orders: if o.oid is None: mlogger.debug(f'Order did={o.did} missing oid.') linked = False if linked: mlogger.debug( f'Cart {cart_rec.name} (did={cart_rec.did}) linked.') update_record(session, Cart, cart_rec.did, linked=True) else: mlogger.debug( f'Cart {cart_rec.name} (did={cart_rec.did}) not linked.') else: mlogger.debug( f'Cart with did={cart_id} not linked (missing record).')
def add_sierra_ids_to_orders(source_fh, system_id): mlogger.debug(f'Linking IDs initiated system_id-{system_id}.') sids = get_sierra_ids(source_fh, system_id) try: unique_carts = set() with session_scope() as session: for sid in sids: wlo, oid, bid = sid ord_rec = retrieve_record(session, Order, wlo=wlo) if ord_rec: # record affected cart_id unique_carts.add(ord_rec.cart_id) # update ord rec update_record(session, Order, ord_rec.did, oid=oid, bid=bid) mlogger.debug(f'Record updated: order_id={ord_rec.did}, ' f'wlo={wlo}, oid={oid}, bid={bid}') session.flush() # check which carts are linked determine_carts_linked(session, unique_carts) mlogger.debug('Linking completed.') except Exception as exc: _, _, exc_traceback = sys.exc_info() tb = format_traceback(exc, exc_traceback) mlogger.error('Unhandled error on linking IDs.' f'Traceback: {tb}') raise BabelError(exc)
def assign_blanketPO_to_cart(cart_id): try: with session_scope() as session: cart_rec = retrieve_record(session, Cart, did=cart_id) if cart_rec.blanketPO is None: res = retrieve_unique_vendor_codes_from_cart( session, cart_id, cart_rec.system_id) vendor_codes = [code[0] for code in res] blanketPO = create_blanketPO(vendor_codes) unique = True n = 0 while unique: try: update_record(session, Cart, cart_id, blanketPO=blanketPO) session.flush() unique = False except IntegrityError: session.rollback() n += 1 blanketPO = create_blanketPO(vendor_codes, n) except Exception as exc: _, _, exc_traceback = sys.exc_info() tb = format_traceback(exc, exc_traceback) mlogger.error('Unhandled error on assigning blanketPo to cart.' f'Traceback: {tb}') raise BabelError(exc)
def update_resource(resource_id, **kwargs): try: with session_scope() as session: update_record(session, Resource, resource_id, **kwargs) except Exception as exc: _, _, exc_traceback = sys.exc_info() tb = format_traceback(exc, exc_traceback) mlogger.error('Unhandled error on updating resource.' f'Traceback: {tb}') raise BabelError(exc)
def apply_fund_to_cart(system_id, cart_id, fund_codes): try: with session_scope() as session: cart_rec = retrieve_record(session, Cart, did=cart_id) ord_recs = retrieve_records(session, Order, cart_id=cart_id) for code in fund_codes: fund_rec = retrieve_record(session, Fund, code=code, system_id=system_id) fund_audn, fund_mat, fund_branch, fund_lib = valid_fund_ids( fund_rec) for orec in ord_recs: audn_match = False mat_match = False library_match = False if orec.audn_id in fund_audn: audn_match = True if orec.matType_id in fund_mat: mat_match = True if cart_rec.library_id in fund_lib: library_match = True for oloc in orec.locations: if oloc.branch_id in fund_branch: mlogger.debug('OrdRec-Fund branch {} match'.format( oloc.branch_id)) if audn_match and library_match and mat_match: # update mlogger.debug( 'Complete match. Updating OrderLocation.') update_record(session, OrderLocation, oloc.did, fund_id=fund_rec.did) else: mlogger.debug( 'Incomplete match: lib={}, audn={}, ' 'mat={}.'.format(library_match, audn_match, mat_match)) except Exception as exc: _, _, exc_traceback = sys.exc_info() tb = format_traceback(exc, exc_traceback) mlogger.error('Unhandled error on applying funds to cart.' f'Traceback: {tb}') raise BabelError(exc)
def save_data(model, did=None, **kwargs): kwargs = convert4datastore(kwargs) try: with session_scope() as session: if did: update_record(session, model, did, **kwargs) else: insert_or_ignore(session, model, **kwargs) except IntegrityError as e: mlogger.error(f'DB IntegrityError while saving {model.__name__} ' f'record with parameters {kwargs}') raise BabelError(e)
def update_fund(**kwargs): """ Adds a new fund with all related data args: system_id: int, datastore did of NYPL or BPL fund_code: str, Sierra fund code describ: str, fund brief description libraries: list, 'branches', 'research' (NYPL only) audns: list, list of 'a', 'j', 'y' values applicable for the fund matTypes: list, material types applicable for the fund """ try: for k, v in kwargs.items(): if not v: if k == 'libraries': kwargs[k] = [] elif k == 'audns': kwargs[k] = [] elif k == 'branches': kwargs[k] = [] elif k == 'matTypes': kwargs[k] = [] else: kwargs[k] = None mlogger.info('Existing fund new parameters: {}'.format(kwargs)) with session_scope() as session: branches, libraries, audns, matTypes = create_fund_joiner_objs( session, **kwargs) update_record(session, Fund, kwargs['did'], code=kwargs['code'], describ=kwargs['describ'], audns=audns, branches=branches, matTypes=matTypes, libraries=libraries) fund_rec = retrieve_record(session, Fund, did=kwargs['did']) mlogger.info(f'Updated record {fund_rec}') except Exception as exc: _, _, exc_traceback = sys.exc_info() tb = format_traceback(exc, exc_traceback) mlogger.error('Unhandled error in Fund update.' f'Traceback: {tb}') raise BabelError(exc)
def save_displayed_order_data(tracker_values): try: with session_scope() as session: for v in tracker_values: order = v['order'] locs = v['grid']['locs'] okwargs = {} locations = [] for l in locs: mlogger.debug('Saving orderLoc data: order_id:{}, ' 'loc_id:{}, frm_id:{}'.format( order['order_id'], l['loc_id'], l['unitFrm'].winfo_id())) lkwargs = {} if l['loc_id'] is not None: lkwargs['did'] = l['loc_id'] if l['branchCbx'].get() != '': rec_id = get_branch_rec_id(session, l['branchCbx'].get()) lkwargs['branch_id'] = rec_id if l['shelfCbx'].get() != '': rec_id = get_shelf_rec_id(session, l['shelfCbx'].get()) lkwargs['shelfcode_id'] = rec_id if l['qtyEnt'].get() != '': lkwargs['qty'] = int(l['qtyEnt'].get()) if l['fundCbx'].get() != '': rec_id = get_fund_rec_id(session, l['fundCbx'].get()) lkwargs['fund_id'] = rec_id # validate here if lkwargs: locations.append(OrderLocation(**lkwargs)) mlogger.debug( 'Saving orderLoc data, params: {}'.format(lkwargs)) okwargs = get_ids_for_order_boxes_values(order) okwargs['locations'] = locations mlogger.debug('Saving order data (id:{}), params: {}'.format( order['order_id'], okwargs)) update_record(session, Order, order['order_id'], **okwargs) except Exception as exc: _, _, exc_traceback = sys.exc_info() tb = format_traceback(exc, exc_traceback) mlogger.error('Unhandled error on saving cart data.' f'Traceback: {tb}') raise BabelError(exc)
def find_matches(cart_id, progbar=None, status_var=None): with session_scope() as session: if status_var: status_var.set('Searching...') if progbar: count = count_records(session, Order, cart_id=cart_id) progbar['value'] = 0 progbar['maximum'] = count cart_rec = retrieve_record(session, Cart, did=cart_id) ord_recs = retrieve_records(session, Order, cart_id=cart_id) for rec in ord_recs: keyword = None if rec.resource.isbn: keyword = rec.resource.isbn babel_dup = babel_resource_match(session, cart_rec.system_id, cart_rec.library_id, isbn=keyword) elif rec.resource.upc: keyword = rec.resource.upc babel_dup = babel_resource_match(upc=keyword) else: catalog_dup = False babel_dup = False catalog_dup = catalog_match(cart_rec.system_id, keyword) mlogger.debug( f'Found following order matches: catalog={catalog_dup}, ' f'babel={babel_dup}') update_record(session, Resource, rec.resource.did, dup_catalog=catalog_dup, dup_babel=babel_dup, dup_timestamp=datetime.now()) if progbar: progbar['value'] += 1 progbar.update() if status_var: status_var.set('Search completed.')
def tabulate_funds(cart_id): """ Calculates amount alocated per fund in the cart args: cart_id: int, datastore cart did returns: tally: list of tuples(code, amount) """ tally = [] df = get_cart_details_as_dataframe(cart_id) for fund, value in df.groupby('fund'): amount = (value['price'] * value['qty']).sum() amount = f'{amount:.2f}' tally.append(f'{fund}:${amount}') with session_scope() as session: update_record(session, Cart, did=cart_id, updated=datetime.now()) return tally
def assign_wlo_to_cart(cart_id): try: with session_scope() as session: # determne how many wlo are needed and reserve them last_wlo_rec = retrieve_last_record(session, Wlos) order_count = count_records(session, Order, cart_id=cart_id) wlo_numbers = wlo_pool(last_wlo_rec.did, order_count) orders = retrieve_records(session, Order, cart_id=cart_id) for o in orders: if o.wlo is None: wlo = wlo_numbers.__next__() update_record(session, Order, o.did, wlo=wlo) insert(session, Wlos, did=wlo) except Exception as exc: _, _, exc_traceback = sys.exc_info() tb = format_traceback(exc, exc_traceback) mlogger.error('Unhandled error on assigning wlo to cart.' f'Traceback: {tb}') raise BabelError(exc)
def save_new_dist_and_grid(system_id, profile_id, grids, branch_idx, shelf_idx, dist=None, grid=None): """ args: system_id: int, did from System table profile_id: int, did from User table grids: dict, grids element of CartView tracker dist: str, name of the new DistSet record grid: str, name of the new DistGrid record """ try: mlogger.debug('Creating new dist/grid from CartView. ' f'system: {system_id}, profile: {profile_id}, ' f'dist: {dist}, grid: {grid}') if profile_id is not None: with session_scope() as session: dist_rec = insert_or_ignore(session, DistSet, system_id=system_id, user_id=profile_id, name=dist) mlogger.debug(f'Dist_rec: {dist_rec}') # check if given grid already exists grid_rec = retrieve_record(session, DistGrid, name=grid, distset_id=dist_rec.did) mlogger.debug(f'Grid_rec: {grid_rec}') # determine new gridLocations locations = [] locs = grids['locs'] for l in locs: if grid_rec: locations.append( GridLocation(distgrid_id=grid_rec.did, branch_id=get_id_from_index( l['branchCbx'].get(), branch_idx), shelfcode_id=get_id_from_index( l['shelfCbx'].get(), shelf_idx), qty=int(l['qtyEnt'].get()))) else: locations.append( GridLocation(branch_id=get_id_from_index( l['branchCbx'].get(), branch_idx), shelfcode_id=get_id_from_index( l['shelfCbx'].get(), shelf_idx), qty=int(l['qtyEnt'].get()))) mlogger.debug(f'New locations: {locations}') if grid_rec: mlogger.debug('Updating existing grid_rec.') update_record(session, DistGrid, grid_rec.did, name=grid, distset_id=dist_rec.did, gridlocations=locations) else: mlogger.debug('Inserting new grid_rec.') insert(session, DistGrid, name=grid, distset_id=dist_rec.did, gridlocations=locations) except ValueError as e: mlogger.error('User attempted to save new grid with incorrect values.' f'Error: {e}') raise BabelError('Your new grid includes invalid values.\n' 'Please make sure branch, shelf, and qty are valid.')
def apply_globals_to_cart(cart_id, widgets): try: with session_scope() as session: # order data okwargs = get_ids_for_order_boxes_values(widgets) # locations dist_id, grid_name = widgets['globgrid'] grid_rec = retrieve_record(session, DistGrid, distset_id=dist_id, name=grid_name) mlogger.debug(f'Applying globally grid {grid_rec}') # resource data rkwargs = {} discount = None if 'discEnt' in widgets: if widgets['discEnt'].get() != '': discount = Decimal(widgets['discEnt'].get()) if 'priceEnt' in widgets: if widgets['priceEnt'].get() != '': list_price = Decimal(widgets['priceEnt'].get()) rkwargs['price_list'] = list_price if discount: rkwargs['price_disc'] = list_price - ( (list_price * discount) / Decimal(100)) else: rkwargs['price_disc'] = list_price mlogger.debug('Global update to prices: {}, discount: {}'.format( rkwargs, discount)) ord_recs = retrieve_records(session, Order, cart_id=cart_id) for rec in ord_recs: if grid_rec: olocs = [] for l in grid_rec.gridlocations: olocs.append( OrderLocation(order_id=rec.did, branch_id=l.branch_id, shelfcode_id=l.shelfcode_id, qty=l.qty)) okwargs['locations'] = olocs update_record(session, Order, rec.did, **okwargs) if rkwargs: update_record(session, Resource, rec.resource.did, **rkwargs) session.flush() if discount is not None: rkwargs['price_disc'] = rec.resource.price_list - ( (rec.resource.price_list * discount) / Decimal(100)) update_record(session, Resource, rec.resource.did, **rkwargs) rkwargs = {} except Exception as exc: _, _, exc_traceback = sys.exc_info() tb = format_traceback(exc, exc_traceback) mlogger.error('Unhandled error on applying globals to cart.' f'Traceback: {tb}') raise BabelError(exc)
def apply_grid_to_selected_orders(order_ids, grid_id, append=False): """ Datastore transaction that appends or replaces current OrderLocation records args: order_ids: list, list of datastore order dids grid_id: int, datastore DistGrid.did append: boolean, True appends to existing locations, False replaces existing locations """ with session_scope() as session: # retrieve grid location data grid_rec = retrieve_record(session, DistGrid, did=grid_id) if append: # add to existing locations for oid in order_ids: ord_rec = retrieve_record(session, Order, did=oid) for gloc in grid_rec.gridlocations: # find duplicates and merge dup = False for oloc in ord_rec.locations: if oloc.branch_id == gloc.branch_id and \ oloc.shelfcode_id == gloc.shelfcode_id: # add quantity to existing oloc dup = True mlogger.debug( 'Updating existing ' f'OrderLocation.did={oloc.did} ' f'with new qty={oloc.qty + gloc.qty}') update_record(session, OrderLocation, oloc.did, order_id=oid, branch_id=oloc.branch_id, shelfcode_id=oloc.shelfcode_id, qty=oloc.qty + gloc.qty, fund_id=oloc.fund_id) if not dup: mlogger.debug( f'Inserting new OrderLocation for Order.did={oid} ' f'based on DistGrid.did={gloc.did}') insert_or_ignore(session, OrderLocation, order_id=oid, branch_id=gloc.branch_id, shelfcode_id=gloc.shelfcode_id, qty=gloc.qty) else: # replace existing locations for oid in order_ids: # delete exiting locaations loc_recs = retrieve_records(session, OrderLocation, order_id=oid) for oloc in loc_recs: mlogger.debug(f'Deleting OrderLocation.did={oloc.did} ' f'of order.did={oid}') delete_record(session, OrderLocation, did=oloc.did) for gloc in grid_rec.gridlocations: mlogger.debug(f'Inserting new OrderLocation based on ' f'DistGrid.did={gloc.did}') insert_or_ignore(session, OrderLocation, order_id=oid, branch_id=gloc.branch_id, shelfcode_id=gloc.shelfcode_id, qty=gloc.qty)
def save_grid_data(**kwargs): """ used in GridView """ locs = [] for loc in kwargs['gridlocs']: branch_id = get_id_from_index(loc['branch'], kwargs['branch_idx']) shelf_id = get_id_from_index(loc['shelf'], kwargs['shelf_idx']) if loc['gridloc_id']: locs.append( GridLocation( did=loc['gridloc_id'], distgrid_id=loc['distgrid_id'], branch_id=branch_id, shelfcode_id=shelf_id, qty=loc['qty'])) else: if loc['distgrid_id']: locs.append( GridLocation( distgrid_id=loc['distgrid_id'], branch_id=branch_id, shelfcode_id=shelf_id, qty=loc['qty'] )) else: locs.append( GridLocation( branch_id=branch_id, shelfcode_id=shelf_id, qty=loc['qty'] )) with session_scope() as session: try: record = None if kwargs['grid_did']: update_record( session, DistGrid, kwargs['grid_did'], name=kwargs['name'], distset_id=kwargs['distset_id'], gridlocations=locs) record = retrieve_record( session, DistGrid, name=kwargs['name'], distset_id=kwargs['distset_id']) mlogger.debug( f'Updated record {record}') else: record = insert( session, DistGrid, name=kwargs['name'], distset_id=kwargs['distset_id'], gridlocations=locs) mlogger.debug( f'Added new record {record}') session.expunge_all() return record except IntegrityError as e: raise BabelError(e) except InternalError as e: raise BabelError(e)