def update(self, usage_id, recalculate=False, **mod_data): usage = usage_store.get(usage_id) if not recalculate: # attrs that force cost recalculation cost_affecting_attrs = set(('start_time', 'end_time', 'resource_id', 'quantity', 'member', 'cost')) recalculate = bool(cost_affecting_attrs.intersection(mod_data.keys())) recalculate = recalculate and not usage.cancelled_against if recalculate: usage_data = dict(member_id=mod_data.get('member', usage.member), resource_id=mod_data.get('resource_id', usage.resource_id), resource_owner=mod_data.get('resource_owner', usage.resource_owner), quantity=mod_data.get('quantity', usage.quantity), starts=mod_data.get('start_time', usage.start_time), cost=mod_data.get('cost'), ends=mod_data.get('end_time', usage.end_time) ) result = pricinglib.calculate_cost(return_taxes=True, **usage_data) mod_data.update(calculated_cost = result['calculated_cost'], total = result['total'], tax_dict = result['taxes'], pricing = pricinglib.pricings.get(usage.member, usage.resource_id, usage.start_time) if usage.resource_id else None) if not 'cost' in mod_data: if usage.cost is None: mod_data['cost'] = result['calculated_cost'] if 'usages' in mod_data: usages = mod_data.pop('usages') for suggested_usage_id in usage.usages_suggested: usage_collection.delete(suggested_usage_id) relations = resourcelib.resource_resource.get_relations(usage.resource_id) mod_data['usages_suggested'] = add_suggested_usages(usage.resource_owner, usage, relations[False], usages) if 'start_time' in mod_data or 'end_time' in mod_data: start_time = mod_data.get('start_time', usage.start_time) end_time = mod_data.get('end_time', usage.end_time) update_slots(usage_id, usage.resource_id, start_time, end_time) usage_store.update(usage_id, **mod_data)
def new(self, resource_id, resource_name, resource_owner, member, start_time, end_time=None, quantity=1, cost=None, tax_dict={}, invoice=None, cancelled_against=None, calculated_cost=None, notes=None, usages=[], name=None, description=None, no_of_people=0, suppress_notification=False, public=False, repetition_id=None): # TODO shouldn't we name the parameter member_id and not member if quantity is None: quantity = 1 if not end_time: end_time = start_time resource = resourcelib.resource_resource.info(resource_id) if resource_id else None member_dict = member_store.get(member, ['id', 'first_name', 'name', 'email']) if resource: resource_owner = resource.owner if not resource.enabled or resource.archived: raise be.errors.ErrorWithHint('Resource is either not enabled or is archived') if end_time < start_time: raise be.errors.ErrorWithHint('Start time is less than end time') created = datetime.datetime.now() if cancelled_against: total = cost + costlib.to_decimal(tax_dict.get('total', 0)) else: result = pricinglib.calculate_cost(member_id=member, resource_id=resource_id, resource_owner=resource_owner, quantity=quantity, starts=start_time, ends=end_time, cost=cost, return_taxes=True) calculated_cost = result['calculated_cost'] total = result['total'] tax_dict = result['taxes'] if cost is None: cost = calculated_cost pricing = pricinglib.pricings.get(member, resource_id, start_time) if resource_id else None data = dict(resource_id=resource_id, resource_name=resource_name, resource_owner=resource_owner, quantity=quantity, calculated_cost=calculated_cost, cost=cost, total=total, tax_dict=tax_dict, invoice=invoice, start_time=start_time, end_time=end_time, member=member, created_by=env.context.user_id, created=created, cancelled_against=cancelled_against, pricing=pricing, notes=notes, name=name, description=description, no_of_people=no_of_people, public=public, repetition_id=repetition_id) if resource and (resource.calc_mode == resourcelib.CalcMode.quantity_based): data['end_time'] == start_time else: data['quantity'] == 1 if not cancelled_against and not resource_id == 0: usages_dict = dict((usage['resource_id'], usage) for usage in usages) relations = resourcelib.resource_resource.get_relations(resource_id) contained_usages_data = [] suggested_usages_data = [] for res in relations[True]: usage = usages_dict.get(res.id, {}) new_data = dict(resource_id=res.id, resource_name=res.name, resource_owner=resource_owner, member=member, suppress_notification=True, start_time=start_time, end_time=start_time if res.calc_mode == resourcelib.CalcMode.quantity_based else data['end_time'], quantity=usage.get('quantity', 1)) contained_usages_data.append(new_data) contained_usage_ids = [self.new(**new_data) for new_data in contained_usages_data] suggested_usage_ids = add_suggested_usages(resource['owner_id'], data, relations[False], usages) also_booked_text = ', '.join(res.name for res in relations[False] if res.id in usages_dict) data['usages_contained'] = contained_usage_ids data['usages_suggested'] = suggested_usage_ids usage_id = usage_store.add(**data) if resource and resource.calc_mode == resourcelib.CalcMode.time_based: reserve_slots(usage_id, resource.id, start_time, end_time) suppress_email = cancelled_against or suppress_notification or resource_id == 0 or \ (resource and resource.calc_mode != resourcelib.CalcMode.time_based) if not suppress_email: owner = bizplace_store.get(resource_owner, ['id', 'name', 'booking_email', 'currency', 'host_email', 'phone']) also_booked_text = 'Also booked: ' + also_booked_text if also_booked_text else '' email_data = dict(LOCATION=owner.name, MEMBER_EMAIL=member_dict.email, BOOKING_CONTACT=owner.booking_email or owner.host_email, MEMBER_FIRST_NAME=member_dict.first_name, RESOURCE=resource_name, BOOKING_START=commonlib.helpers.time4human(start_time), BOOKING_END=commonlib.helpers.time4human(end_time), BOOKING_DATE=commonlib.helpers.date4human(start_time), CURRENCY=owner.currency, COST=cost, HOSTS_EMAIL=owner.host_email, LOCATION_PHONE=owner.phone) mailtext = messagecustlib.get(owner.id, 'booking_confirmation') notification = commonlib.messaging.messages.booking_confirmation(email_data, overrides=dict(plain=mailtext, bcc='*****@*****.**')) notification.build() notification.email() a_data = dict(resource_id=resource_id, resource_name=resource_name, resource_owner=resource_owner, member_id=member_dict.id, member_name=member_dict.name, start_time=start_time, end_time=end_time, actor_id=env.context.user_id, actor_name=env.context.name, created=created) activity_id = activitylib.add('booking', 'booking_created', a_data, created) return usage_id