def qn(self): qn = [] # cats. for fname, mrel in [ ('cats__in', self.loccats), ('user__cats__in', self.usercats), ('place__cats__in', self.placecats), ]: if mrel.exists(): mrel = utils.tree_all_downs(mrel.all()) qn.append(_q(fname, mrel)) # addresses. tmpl = 'address__%s__in' for suffix, mrel in [ ('area', self.areas), ('area__city', self.cities), ('area__city__state', self.states), ('area__city__state__country', self.countries), ('area__zip', self.zips), ('area__zip__brick', self.bricks), ]: if mrel.exists(): qn.append(_qn_or([ _q('%saddress__%s__in' % (prefix, suffix), mrel.all()) for prefix in [ '', 'place__' ] ])) # print 'VisitCond', self, qn return qn
def _node_data(_node): d = cached.get(_node) iscached = d is not None if not iscached: _upnodes = utils.tree_ups(_node) _itemcats = utils.tree_all_downs(utils.list_flatten(_upnodes, lambda enode: enode.itemcats.all())) d = dict( upnodes = _upnodes, itemcats = _itemcats, items = ItemCat.els_get(_itemcats), ) cached[_node] = d # print '_node_data cached', iscached, _node, d return d
def get_queryset(self): qset = super(AbstractView, self).get_queryset() for name, deep in [ ('incats', True), ('cats', False) ]: cats = self.request.QUERY_PARAMS.get(name) if cats: model = qset.model # self.get_serializer().opts.model field = model._meta.get_field('cats') if field: cats = utils.str_ints(cats) if cats: if deep: target = field.related.parent_model cats = utils.list_compact([ utils.db_get(target, cat) for cat in cats ]) cats = utils.tree_all_downs(cats) qset = qset.filter(cats__in=cats) # print 'get_queryset', self, type(qset), model, cats return qset
def _reps_usercats(): ucats = utils.tree_all_downs(form.repusercats.all()) ucats2 = baseuser.allcats() nreps = ucats & ucats2 # print '_reps_usercats', baseuser, len(ucats), len(ucats2), len(nreps) return _reps(False, repdict_usercats, nreps)
def _reps_items(): reps1 = form.repitems.all() repcats = utils.tree_all_downs(form.repitemcats.all()) reps2 = ItemCat.els_get(repcats) nreps = (reps1 | reps2).distinct() return _reps(True, repdict_items, nreps)
def allcats(self): return utils.tree_all_downs(self.cats.all())
def _generate(self): sys = Sys.objects.first() print '_generate', self, sys qn = [] # collection of multiple conds. def _qn_and_or(_qn, _isand): return _qn_and(_qn) if _isand else _qn_or(_qn) for cond in self.conds.all(): eqn = cond.qn() if eqn: qn.append(_qn_and_or(eqn, not self.isand)) if not qn: # not any ([ getattr(self, e).exists() for e in 'usercats loccats areas cities states countries zips bricks'.split() ]) # raise ValidationError('Must select at least one condition for Users / Locs.') self.generate = False self.save() return # revert generate and ABORT, so we do NOT waste this builder. if qn: locs = Loc.objects.filter(_qn_and_or(qn, self.isand)) # print 'query', locs.query locs = list(locs) else: locs = [] def _sortkey(eloc): addr = eloc.addr() by = self.orderby def _val(): v = addr.area if by == 'area': return v if by in [ 'zip', 'brick' ]: v = v.zip return v if by == 'zip' else v.brick v = v.city if by == 'city': return v v = v.state if by == 'state': return v v = v.country if by == 'country': return v error val = _val().name # print '_sortkey', by, val, eloc return val locs = sorted(locs, key=_sortkey) print 'locs', len(locs), locs pcats = utils.tree_all_downs(self.periodcats.all()) pn1 = list(PeriodCat.els_get(pcats)) pn2 = list(self.periods.all()) pn = sorted(set(pn1 + pn2), key=lambda e: e.end) print 'pn', pn def _day(week, date): return getattr(week, utils.weekdays[date.weekday()]) def _onoff(dt, week, sources, suffix): day = _day(week, dt) # print '_onoff', dt, week, day ok = False if day: dtdate = dt.date() dttime = dt.time() intime = False for time in day.times.all(): if dttime >= time.start and dttime <= time.end: intime = True break if intime: sources = utils.list_compact(sources) # remove None's. def _get(prefix, cmp2, checkdate): xn = utils.list_flatten(sources, lambda e: getattr(e, prefix + suffix).all()) # print '_onoff._get', cmp2, xn def _filter(e): return cmp2 >= e.start and cmp2 <= e.end and (not e.date or e.date == dtdate if checkdate else True) return utils.list_last(sorted( [ e for e in xn if _filter(e) ], key = lambda e: e.start, )) def _ison(pt): return not pt or pt.on operiod = _get('onoffperiod', dtdate, False) if _ison(operiod): otime = _get('onofftime', dttime, True) if _ison(otime): ok = True # if not ok: print '_onoff - FAILED', dt return ok with transaction.atomic(): mgr = ForceVisit.objects self.qty_slots = 0 self.qty_slots_skips = 0 self.qty_locs = len(locs) self.qty_locs_skips = 0 self.qty_node_skips = 0 nodeskips = 0 visits = [] for ep in pn: start, end = ep.dates() qv = mgr.filter(datetime__range=(start, end)) # query within the current period (start - end). delta = end - start dates = [ start + datetime.timedelta(days=i) for i in range(delta.days + 1) ] week = ep.week or sys.week_period print '_generate > ep', ep, week, start, end # dates for edate in dates: day = _day(week, edate) print '_generate > edate', edate, day if day: def _datetime(_time): # can't use timedelta with simple times. return datetime.datetime.combine(edate, _time) for etime in day.times.all(): dt = _datetime(etime.start) dt2 = _datetime(etime.end) while dt < dt2: self.qty_slots += 1 # print '_generate > slot', dt user = self.node.user ison = _onoff( dt, (user.week_visit if user else None) or sys.week_user_visit, [ user ], '_visit', ) if ison: if qv.filter(node=self.node, datetime=dt).exists(): # visit already generated for the node in this time slot. self.qty_node_skips += 1 print '_generate > qty_node_skips', dt, self.node else: # try (potentially multiple) locs for this specific time slot. tryloc = True locs2 = [] # queue for tried locs, which should be retried in the next time slot. while locs and tryloc: loc = locs.pop(0) if locs else None # print '_tryloc', dt, loc if loc: if qv.filter(loc=loc): # loc already visited during this period. self.qty_locs_skips += 1 print '_generate > qty_locs_skips', dt, loc else: ison = _onoff( dt, loc.week or loc.user.week_visited or sys.week_user_visited, [ loc, loc.user ], '_visited', ) if ison: visit = mgr.create( builder = self, node = self.node, loc = loc, datetime = dt, duration = self.duration, ) print '==> _generate > visit', dt, visit visits.append(visit) tryloc = False else: # print '_generate > SKIP VISITED (locs2 queue)', dt, loc locs2.append(loc) locs[0:0] = locs2 # re-insert in order at the beginning, for immediate try during the subsequent time slots. else: # print '_generate > SKIP VISIT', dt, user pass dt = utils.datetime_plus(dt, self.duration, self.gap) self.qty_visits = len(visits) print 'done > generated visits & remaining locs', self.qty_visits, len(locs) self.save()