def test01(self): """ Initialization. """ #~ print "20130321 test00 started" self.user_root = settings.SITE.user_model(username='******', language='en', user_type='900') self.user_root.save() self.client.force_login(self.user_root) self.assertEqual(1 + 1, 2) # o1 = contacts.Company(name="Example") # o1.save() # o2 = contacts.Company(name="Example") # o2.save() p1 = avanti.Client(first_name="John", last_name="Doe") p1.full_clean() p1.save() # p2 = contacts.Person(first_name="Johny", last_name="Doe") # p2.full_clean() # p2.save() # contacts.Role(person=p1, company=o1).save() # contacts.Role(person=p2, company=o2).save() evt = cal.Event() evt.full_clean() evt.save() guest = cal.Guest(event=evt, partner=p1) guest.full_clean() guest.save() s = cal.GuestsByEvent.request(evt).to_rst() # print('\n'+s) self.assertEqual( s, """\ ================= ====== =============== ================ ======== Participant Role Workflow Absence reason Remark ----------------- ------ --------------- ---------------- -------- (100) from None **? Invited** ================= ====== =============== ================ ======== """) # ba = contacts.Persons.get_action_by_name('merge_row') # self.assertEqual(ba, '') utpl = "/api/cal/OneEvent/{0}?&an=wf3" url = utpl.format(evt.pk) res = self.client.get(url, REMOTE_USER='******') self.assertEqual(res.status_code, 200) res = AttrDict(json.loads(res.content)) self.assertEqual( res.message, "Cannot mark as Took place because 1 participants are Invited.") self.assertEqual(res.success, False)
def post_json_dict(username, url, data, **extra): """Send a POST with given username, url and data. The client is expected to respond with a JSON encoded response. Parse the response's content (which is expected to contain a dict), convert this dict to an AttrDict before returning it. """ res = test_client.post(url, data, REMOTE_USER=username, **extra) assert res.status_code == 200 return AttrDict(json.loads(res.content))
def get_data_rows(cls,ar): qs = VerseText.objects.all() if ar.param_values.p_book: qs = qs.filter(verse__book=ar.param_values.p_book) if ar.param_values.p_chapter: qs = qs.filter(verse__chapter=ar.param_values.p_chapter) verses = dict() versenos = [] for obj in qs.order_by('verse__verseno','verse__verseno_suffix'): k = obj.verse.pk v = verses.get(k,None) if v is None: versenos.append(k) v = AttrDict(pk=k,left='',right='',verse=obj.verse) verses[k] = v if obj.edition == ar.param_values.edition1: v.left = obj.text elif obj.edition == ar.param_values.edition2: v.right = obj.text for k in versenos: yield verses[k]
def post_json_dict(username, url, data, **extra): """Send a POST with given username, url and data. The client is expected to respond with a JSON encoded response. Parse the response's content (which is expected to contain a dict), convert this dict to an AttrDict before returning it. """ res = test_client.post(url, data, REMOTE_USER=username, **extra) if res.status_code != 200: raise Exception("{} gave status code {} instead of 200".format( url, res.status_code)) return AttrDict(json.loads(res.content))
def read_card_data_from_file(fn): fp = open(fn) rv = json.load(fp) fp.close() # dd.logger.info("20181002 json.load({}) returned {}".format( # fn, rv)) if 'success' not in rv: raise Warning(_("Got invalid card data {} from eidreader.").format(rv)) data = AttrDict(rv) if not data.success: raise Warning(_("No card data found: {}").format(data.message)) return data
def cells2row(self, cells): d = {} for i, cell in enumerate(cells): name = self.column_names[i] if name: d[name] = cell i += 1 while i < len(self.headers): name = self.column_names[i] if name: d[name] = None i += 1 #~ logger.info("20121122 cells2row %s -> %s",cells,d) return AttrDict(d)
def discover(): global actor_classes global actors_list global actors_dict assert actors_list is None assert actors_dict is None actors_list = [] actors_dict = AttrDict() logger.debug("actors.discover() : registering %d actors", len(actor_classes)) for cls in actor_classes: register_actor(cls) actor_classes = None
def yaml2dict(data): raw_data = data['card_data'] if not '\n' in raw_data: # a one-line string means that some error occured (e.g. no # card in reader). of course we want to show this to the # user. raise Warning(raw_data) #~ print cd attd = AttrDict(yaml.load(raw_data)) #~ raise Exception("20131108 cool: %s" % cd) if dd.plugins.beid.data_collector_dir: card_number = str(attd.cardNumber) logger.info("Gonna write raw eid card data: %r", raw_data) fn = os.path.join(dd.plugins.beid.data_collector_dir, card_number + '.txt') file(fn, "w").write(raw_data.encode('utf-8')) logger.info("Wrote eid card data to file %s", fn) return attd
def add_filter(self, qs, obj): if isinstance(obj, datetime.date): obj = AttrDict(start_date=obj, end_date=obj) if obj.start_date is None or obj.end_date is None: return qs if self.name == 'started': qs = qs.filter(start_date__gte=obj.start_date) qs = qs.filter(start_date__lte=obj.end_date) elif self.name == 'ended': qs = qs.filter(end_date__isnull=False) qs = qs.filter(end_date__gte=obj.start_date) qs = qs.filter(end_date__lte=obj.end_date) elif self.name == 'active': qs = qs.filter( Q(start_date__isnull=True) | Q(start_date__lte=obj.end_date)) qs = qs.filter( Q(end_date__isnull=True) | Q(end_date__gte=obj.start_date)) return qs
def swap_seqno(self, ar, offset): """ Move this row "up or down" within its siblings """ #~ qs = self.get_siblings() qs = ar.data_iterator if qs is None: return nav = AttrDict(**navinfo(qs, self)) if not nav.recno: return new_recno = nav.recno + offset if new_recno <= 0: return if new_recno > qs.count(): return other = qs[new_recno - 1] prev_seqno = other.seqno other.seqno = self.seqno self.seqno = prev_seqno self.save() other.save()
def client_json_dict(self, meth, username, url, *data, **extra): """Send a POST or PUT to client with given username, url and data. The server is expected to respond with a JSON encoded response. Parse the response's content (which is expected to contain a dict), convert this dict to an AttrDict before returning it. """ ar = settings.SITE.login(username) self.client.force_login(ar.user) extra[settings.SITE.remote_user_header] = username # extra.update(REMOTE_USER=username) # print(20170609, settings.MIDDLEWARE_CLASSES) # print(20170609, settings.AUTHENTICATION_BACKENDS) res = meth(url, *data, **extra) if res.status_code != 200: raise Exception("{} gave status code {} instead of 200".format( url, res.status_code)) content = res.content.decode() try: d = json.loads(content) except ValueError as e: raise ValueError("Invalid JSON {} : {}".format(content, e)) return AttrDict(d)
def setup(self, known_values=None, param_values=None, action_param_values={}, **kw): BaseRequest.setup(self, **kw) #~ 20120111 #~ self.known_values = known_values or self.report.known_values #~ if self.report.known_values: #~ d = dict(self.report.known_values) kv = dict() for k, v in list(self.actor.known_values.items()): kv.setdefault(k, v) if known_values: kv.update(known_values) self.known_values = kv request = self.request if self.actor.parameters is not None: pv = self.actor.param_defaults(self) for k in list(pv.keys()): if k not in self.actor.parameters: raise Exception( "%s.param_defaults() returned invalid keyword %r" % (self.actor, k)) # New since 20120913. E.g. newcomers.Newcomers is a # simple pcsw.Clients with # known_values=dict(client_state=newcomer) and since there # is a parameter `client_state`, we override that # parameter's default value. for k, v in list(self.known_values.items()): if k in pv: pv[k] = v # New since 20120914. MyClientsByGroup has a `group` as # master, this must also appear as `group` parameter # value. Lino now understands tables where the master_key # is also a parameter. if self.actor.master_key is not None: if self.actor.master_key in pv: pv[self.actor.master_key] = self.master_instance if param_values is None: if request is not None: # call get_layout_handle to make sure that # params_store has been created: self.actor.params_layout.get_layout_handle( self.renderer.plugin) ps = self.actor.params_layout.params_store # print('20160329 requests.py', ps, self.actor.parameters) if ps is not None: pv.update(ps.parse_params(request)) else: raise Exception( "20160329 params_layout {0} has no params_store " "in {1!r}".format(self.actor.params_layout, self.actor)) else: for k in list(param_values.keys()): if k not in pv: raise Exception( "Invalid key '%s' in param_values of %s " "request (possible keys are %s)" % (k, self.actor, list(pv.keys()))) pv.update(param_values) # print("20160329 ok", pv) self.param_values = AttrDict(**pv) # self.actor.check_params(self.param_values) action = self.bound_action.action if action.parameters is not None: if len(self.selected_rows) == 1: apv = action.action_param_defaults(self, self.selected_rows[0]) else: apv = action.action_param_defaults(self, None) # msg = "20170116 selected_rows is {} for {!r}".format( # self.selected_rows, action) # raise Exception(msg) if request is not None: apv.update( action.params_layout.params_store.parse_params(request)) self.action_param_values = AttrDict(**apv) # action.check_params(action_param_values) self.set_action_param_values(**action_param_values) self.bound_action.setup_action_request(self)
def old_as_odt(self): from xhtml2odt import ODTFile from lino.utils import AttrDict from lino.utils.html2xhtml import html2xhtml options = AttrDict( url="", with_network=False, verbose=True, template=self.input_template, top_header_level=1, img_width="8cm", img_height="6cm", ) # ~ version=False # help="Show the version and exit") #~ input=input", metavar="FILE", #~ help="Read the html from this file") #~ parser.add_option("-o", "--output", dest="output", metavar="FILE", #~ help="Location of the output ODT file") #~ parser.add_option("-t", "--template", dest="template", metavar="FILE", #~ help="Location of the template ODT file") #~ parser.add_option("-u", "--url", dest="url", #~ help="Use this URL for relative links") #~ parser.add_option("-v", "--verbose", dest="verbose", #~ action="store_true", default=False, #~ help="Show what's going on") #~ parser.add_option("--html-id", dest="htmlid", metavar="ID", #~ help="Only export from the element with this ID") #~ parser.add_option("--replace", dest="replace_keyword", #~ default="ODT-INSERT", metavar="KEYWORD", #~ help="Keyword to replace in the ODT template " #~ "(default is %default)") #~ parser.add_option("--cut-start", dest="cut_start", #~ default="ODT-CUT-START", metavar="KEYWORD", #~ help="Keyword to start cutting text from the ODT " #~ "template (default is %default)") #~ parser.add_option("--cut-stop", dest="cut_stop", #~ default="ODT-CUT-STOP", metavar="KEYWORD", #~ help="Keyword to stop cutting text from the ODT " #~ "template (default is %default)") #~ parser.add_option("--top-header-level", dest="top_header_level", #~ type="int", default="1", metavar="LEVEL", #~ help="Level of highest header in the HTML " #~ "(default is %default)") #~ parser.add_option("--img-default-width", dest="img_width", #~ metavar="WIDTH", default="8cm", #~ help="Default image width (default is %default)") #~ parser.add_option("--img-default-height", dest="img_height", #~ metavar="HEIGHT", default="6cm", #~ help="Default image height (default is %default)") #~ parser.add_option("--dpi", dest="img_dpi", type="int", #~ default=96, metavar="DPI", help="Screen resolution " #~ "in Dots Per Inch (default is %default)") #~ parser.add_option("--no-network", dest="with_network", #~ action="store_false", default=True, #~ help="Do not download remote images") #~ options, args = parser.parse_args() odtfile = ODTFile(options) odtfile.open() xhtml = ''.join([ln for ln in self.main.html_lines()]) xhtml = html2xhtml(xhtml) #~ xhtml = "<DIV>%s</DIV>" % xhtml xhtml = """\ <html xmlns="http://www.w3.org/1999/xhtml"><body>%s</body></html>""" % xhtml #~ xhtml = "<p>%s</p>" % xhtml if True: f = open("before.xml", "wt") f.write(xhtml.encode('utf-8')) f.close() #~ logger.info("Gonna do it with %r",xhtml) xhtml = odtfile.xhtml_to_odt(xhtml) if True: f = open("after.xml", "wt") f.write(xhtml) #~ f.write(xhtml.encode('utf-8')) f.close() return xhtml
def __new__(meta, classname, bases, classDict): #~ if not classDict.has_key('app_label'): #~ classDict['app_label'] = cls.__module__.split('.')[-2] """ attributes that are never inherited from base classes: """ # classDict.setdefault('name',classname) # ~ classDict.setdefault('label',None) # 20130906 #~ classDict.setdefault('related_name',None) #~ classDict.setdefault('button_label',None) classDict.setdefault('title', None) classDict.setdefault('help_text', None) classDict.setdefault('abstract', False) declared_label = classDict.pop('label', None) if declared_label is not None: classDict.update(_label=declared_label) declared_known_values = classDict.pop('known_values', None) if declared_known_values is not None: classDict.update(_known_values=declared_known_values) declared_editable = classDict.pop('editable', None) if declared_editable is not None: classDict.update(_editable=declared_editable) cls = type.__new__(meta, classname, bases, classDict) #~ if not classDict.has_key('label'): #~ cls.label = ClassProperty(cls.get_actor_label) # ~ meta.label = property(cls.get_actor_label.im_func) # 20130906 #~ if not classDict.has_key('known_values'): #~ cls.known_values = ClassProperty(cls.get_known_values) # ~ meta.known_values = property(cls.get_known_values.im_func) # 20130906 #~ if cls.is_abstract(): #~ actions.register_params(cls) """ On 20110822 I thought "A Table always gets the app_label of its model, you cannot set this yourself in a subclass because otherwise it gets complex when inheriting reports from other app_labels." On 20110912 I cancelled change 20110822 because PersonsByOffer should clearly get app_label 'jobs' and not 'contacts'. """ if classDict.get('app_label', None) is None: # Figure out the app_label by looking one level up. # For 'django.contrib.sites.models', this would be 'sites'. x = cls.__module__.split('.') if len(x) > 1: cls.app_label = x[-2] cls.actor_id = cls.app_label + '.' + cls.__name__ cls._setup_done = False cls._setup_doing = False cls.virtual_fields = {} cls._constants = {} cls.actions = AttrDict() cls._actions_list = [] # 20121129 # inherit virtual fields defined on parent Actors for b in bases: bd = getattr(b, 'virtual_fields', None) if bd: cls.virtual_fields.update(bd) if True: # (20130817) tried to move this to a later moment for k, v in list(classDict.items()): cls.register_class_attribute(k, v) #~ if classname == 'Tasks': #~ logger.info("20130817 no longer added actor vfs") #~ cls.params = [] #~ for k,v in classDict.items(): #~ if isinstance(v,models.Field): #~ v.set_attributes_from_name(k) #~ v.table = cls #~ cls.params.append(v) #~ cls.install_params_on_actor() if classname not in ('Table', 'AbstractTable', 'VirtualTable', 'Action', 'Actor', 'Frame', 'ChoiceList', 'Workflow', 'EmptyTable', 'Dialog'): if actor_classes is None: #~ logger.debug("%s definition was after discover",cls) pass elif not cls.__name__.startswith('unused_'): # ~ cls.class_init() # 20120115 actor_classes.append(cls) #~ logger.debug("ActorMetaClass.__new__(%s)", cls) return cls
def write_odt_file(self, target): #~ from lino.utils import iif #~ from lino.utils import AttrDict #~ from lino.utils.html2xhtml import html2xhtml assert os.path.abspath( self.input_template) != os.path.abspath(target) if os.path.exists(target): os.remove(target) options = AttrDict( url="", template=self.input_template, output=target, with_network=True, verbose=True, top_header_level=1, img_width="8cm", img_height="6cm", ) # ~ version=False # help="Show the version and exit") #~ input=input", metavar="FILE", #~ help="Read the html from this file") #~ parser.add_option("-o", "--output", dest="output", metavar="FILE", #~ help="Location of the output ODT file") #~ parser.add_option("-t", "--template", dest="template", metavar="FILE", #~ help="Location of the template ODT file") #~ parser.add_option("-u", "--url", dest="url", #~ help="Use this URL for relative links") #~ parser.add_option("-v", "--verbose", dest="verbose", #~ action="store_true", default=False, #~ help="Show what's going on") #~ parser.add_option("--html-id", dest="htmlid", metavar="ID", #~ help="Only export from the element with this ID") #~ parser.add_option("--replace", dest="replace_keyword", #~ default="ODT-INSERT", metavar="KEYWORD", #~ help="Keyword to replace in the ODT template " #~ "(default is %default)") #~ parser.add_option("--cut-start", dest="cut_start", #~ default="ODT-CUT-START", metavar="KEYWORD", #~ help="Keyword to start cutting text from the ODT " #~ "template (default is %default)") #~ parser.add_option("--cut-stop", dest="cut_stop", #~ default="ODT-CUT-STOP", metavar="KEYWORD", #~ help="Keyword to stop cutting text from the ODT " #~ "template (default is %default)") #~ parser.add_option("--top-header-level", dest="top_header_level", #~ type="int", default="1", metavar="LEVEL", #~ help="Level of highest header in the HTML " #~ "(default is %default)") #~ parser.add_option("--img-default-width", dest="img_width", #~ metavar="WIDTH", default="8cm", #~ help="Default image width (default is %default)") #~ parser.add_option("--img-default-height", dest="img_height", #~ metavar="HEIGHT", default="6cm", #~ help="Default image height (default is %default)") #~ parser.add_option("--dpi", dest="img_dpi", type="int", #~ default=96, metavar="DPI", help="Screen resolution " #~ "in Dots Per Inch (default is %default)") #~ parser.add_option("--no-network", dest="with_network", #~ action="store_false", default=True, #~ help="Do not download remote images") #~ options, args = parser.parse_args() self.odtfile = MyODTFile(options) context = dict(iif=iif) context.update(book=self) self.odtfile.render(context)
def test01(self): """ Initialization. """ #~ print "20130321 test00 started" self.user_root = settings.SITE.user_model(username='******', language='en', user_type='900') self.user_root.save() self.client.force_login(self.user_root) self.assertEqual(1 + 1, 2) o1 = contacts.Company(name="Example") o1.save() o2 = contacts.Company(name="Example") o2.save() p1 = contacts.Person(first_name="John", last_name="Doe") p1.full_clean() p1.save() p2 = contacts.Person(first_name="Johny", last_name="Doe") p2.full_clean() p2.save() contacts.Role(person=p1, company=o1).save() contacts.Role(person=p2, company=o2).save() evt = cal.Event() evt.full_clean() evt.save() guest = cal.Guest(event=evt, partner=p1) guest.full_clean() guest.save() # s = contacts.ContactsByOrganisation.request(o1).to_rst() s = contacts.RolesByCompany.request(o1).to_rst() # print('\n'+s) self.assertEqual( s, """\ ========== ========== Person Function ---------- ---------- John Doe ========== ========== """) s = contacts.RolesByCompany.request(o2).to_rst() # print('\n'+s) self.assertEqual( s, """\ =========== ========== Person Function ----------- ---------- Johny Doe =========== ========== """) # ba = contacts.Persons.get_action_by_name('merge_row') # self.assertEqual(ba, '') utpl = "/api/contacts/Persons/{0}?fv={1}&fv=&fv=&fv=&fv=false&fv=fff&an=merge_row" url = utpl.format(p1.pk, p1.pk) res = self.client.get(url, REMOTE_USER='******') self.assertEqual(res.status_code, 200) res = AttrDict(json.loads(res.content)) self.assertEqual(res.message, "Cannot merge an instance to itself.") self.assertEqual(res.success, False) url = utpl.format(p1.pk, '') res = self.client.get(url, REMOTE_USER='******') self.assertEqual(res.status_code, 200) res = AttrDict(json.loads(res.content)) self.assertEqual(res.message, "You must specify a merge target.") self.assertEqual(res.success, False) url = utpl.format(p1.pk, p2.pk) res = self.client.get(url, REMOTE_USER='******') self.assertEqual(res.status_code, 200) res = AttrDict(json.loads(res.content)) # print(res) expected = '<div class="htmlText"><p>Are you sure you want to merge John Doe into Johny Doe?</p><ul><li>1 Presences, 1 Contact persons <b>will get reassigned.</b></li><li>John Doe will be deleted</li></ul></div>' self.assertEqual(res.message, expected) self.assertEqual(res.success, True) self.assertEqual(res.close_window, True) self.assertEqual(res.xcallback['buttons'], [['yes', 'Yes'], ['no', 'No']]) self.assertEqual(res.xcallback['title'], "Confirmation") # pprint(res.xcallback) cbid = res.xcallback['id'] # add callback uid adn choice into request and send again. url += "&" + urlencode({"xcallback__" + cbid: "yes"}) res = self.client.get(url, REMOTE_USER='******') self.assertEqual(res.status_code, 200) res = AttrDict(json.loads(res.content)) # print(res) self.assertEqual( res.message, 'Merged John Doe into Johny Doe. Updated 2 related rows.') self.assertEqual(res.success, True) s = contacts.Roles.request().to_rst() # print('\n'+s) self.assertEqual( s, """\ ==== ========== =========== ============== ID Function Person Organisation ---- ---------- ----------- -------------- 1 Johny Doe Example 2 Johny Doe Example ==== ========== =========== ============== """) s = cal.Guests.request().to_rst() # print('\n'+s) self.assertEqual( s, """\ =========== ====== ============= ======== ================================ Person Role Workflow Remark Calendar entry ----------- ------ ------------- -------- -------------------------------- Johny Doe **Invited** Calendar entry #1 (23.10.2014) =========== ====== ============= ======== ================================ """) # self.fail("TODO: execute a merge action using the web interface") # 20130418 server traceback caused when a pdf view of a table # was requested through the web interface. TypeError: # get_handle() takes exactly 1 argument (2 given) url = settings.SITE.buildurl( 'api/countries/Countries?cw=189&cw=45&cw=45&cw=36&ch=&ch=&ch=&ch=&ch=&ch=&ci=name&ci=isocode&ci=short_code&ci=iso3&name=0&an=as_pdf' ) msg = 'Using remote authentication, but no user credentials found.' if False: # not converted after 20170609 try: response = self.client.get(url) self.fail("Expected '%s'" % msg) except Exception as e: self.assertEqual(str(e), msg) # response = self.client.get(url, REMOTE_USER='******') # self.assertEqual(response.status_code, 403, # "Status code for anonymous on GET %s" % url) from appy.pod import PodError """ If oood is running, we get a 302, otherwise a PodError """ try: response = self.client.get(url, REMOTE_USER='******') #~ self.assertEqual(response.status_code,200) result = self.check_json_result(response, 'success open_url') self.assertEqual( result['open_url'], "/media/cache/appypdf/127.0.0.1/countries.Countries.pdf") except PodError as e: pass
def card2client(cls,data): "does the actual conversion" kw = dict() #~ assert not settings.SITE.use_eid_jslib #~ assert not settings.SITE.has_plugin(BeIdJsLibPlugin): data = data['card_data'] if not '\n' in data: raise Warning(data) #~ print cd data = AttrDict(yaml.load(data)) #~ raise Exception("20131108 cool: %s" % cd) kw.update(national_id=ssin.format_ssin(str(data.nationalNumber))) kw.update(first_name=join_words( data.firstName, data.middleName)) kw.update(last_name=data.name) card_number = str(data.cardNumber) if data.photo: fn = card_number_to_picture_file(card_number) if os.path.exists(fn): logger.warning("Overwriting existing image file %s.",fn) fp = file(fn,'wb') fp.write(base64.b64decode(data.photo)) fp.close() #~ print 20121117, repr(data['picture']) #~ kw.update(picture_data_encoded=data['picture']) if isinstance(data.dateOfBirth,basestring): data.dateOfBirth = IncompleteDate(*data.dateOfBirth.split('-')) kw.update(birth_date=data.dateOfBirth) kw.update(card_valid_from=data.cardValidityDateBegin) kw.update(card_valid_until=data.cardValidityDateEnd) kw.update(card_number=card_number) kw.update(card_issuer=data.cardDeliveryMunicipality) if data.nobleCondition: kw.update(noble_condition=data.nobleCondition) kw.update(street=data.streetAndNumber) #~ kw.update(street_no=data['streetNumber']) #~ kw.update(street_box=data['boxNumber']) if True: # kw['street'] and not (kw['street_no'] or kw['street_box']): kw = street2kw(kw['street'],**kw) kw.update(zip_code=str(data.zip)) if data.placeOfBirth: kw.update(birth_place=data.placeOfBirth) pk = data.reader.upper() msg1 = "BeIdReadCardToClientAction %s" % kw.get('national_id') #~ try: country = countries.Country.objects.get(isocode=pk) kw.update(country=country) #~ except countries.Country.DoesNotExist,e: #~ except Exception,e: #~ logger.warning("%s : no country with code %r",msg1,pk) #~ BE = countries.Country.objects.get(isocode='BE') #~ fld = countries.City._meta.get_field() kw.update(city=countries.City.lookup_or_create( 'name',data.municipality,country=country)) def sex2gender(sex): if sex == 'MALE' : return dd.Genders.male if sex == 'FEMALE' : return dd.Genders.female logger.warning("%s : invalid gender code %r",msg1,sex) kw.update(gender=sex2gender(data.gender)) def doctype2cardtype(dt): #~ if dt == 1: return BeIdCardTypes.get_by_value("1") rv = BeIdCardTypes.get_by_value(str(dt)) logger.info("20130103 documentType %r --> %r",dt,rv) return rv kw.update(card_type=doctype2cardtype(data.documentType)) return kw
def test_checkin_guest(self): """Test whether notifications are being emitted. - when a visitor checks in - when a client is modified - when a coaching is created or modified - when a note is created or modified """ User = settings.SITE.user_model Message = rt.models.notify.Message Note = rt.models.notes.Note NoteType = rt.models.notes.EventType Guest = rt.models.cal.Guest Event = rt.models.cal.Event EventType = rt.models.cal.EventType Client = rt.models.pcsw.Client ClientStates = rt.models.pcsw.ClientStates Coaching = rt.models.coachings.Coaching ContentType = rt.models.contenttypes.ContentType self.assertEqual(settings.SITE.use_websockets, False) robin = self.create_obj(User, username='******', user_type=UserTypes.admin, language="en") caroline = self.create_obj(User, username='******', user_type='200', language="fr") alicia = self.create_obj(User, username='******', first_name="Alicia", user_type='120', language="fr") roger = self.create_obj(User, username='******', user_type='420', language="en") ses = rt.login('robin') translation.activate('fr') first = self.create_obj(Client, first_name="First", last_name="Gérard", client_state=ClientStates.coached) second = self.create_obj(Client, first_name="Second", last_name="Gérard", client_state=ClientStates.coached) self.create_obj(Coaching, client=second, start_date=i2d(20130501), end_date=i2d(20140501), user=caroline) second_roger = self.create_obj(Coaching, client=second, start_date=i2d(20140501), user=roger) self.create_obj(Coaching, client=second, start_date=i2d(20140520), user=alicia) nt = self.create_obj(NoteType, name="System note") settings.SITE.site_config.update(system_note_type=nt) consultation = self.create_obj(EventType, name="consultation") # gr = self.create_obj(GuestRole, name="client") event = self.create_obj(Event, event_type=consultation, user=caroline) guest = self.create_obj(Guest, event=event, partner=first) self.assertEqual(str(guest), 'Présence #1 (22.05.2014)') # Checkin a guest res = ses.run(guest.checkin) # 'GÉRARD First (100) has started waiting for caroline' self.assertEqual( res, { 'message': "GÉRARD First (100) a commencé d'attendre caróline", 'success': True, 'refresh': True }) # it has caused a notification message: self.assertEqual(Message.objects.count(), 1) msg = Message.objects.all()[0] self.assertEqual(msg.user.username, 'caróline') self.assertEqual(msg.subject, "GÉRARD First (100) a commencé d'attendre caróline") # it does *not* cause a system note: self.assertEqual(Note.objects.count(), 0) # When a client is modified, all active coaches get a # notification. # Note that Caroline doesn't get a notification because her # coaching is not active. # Alicia doesn't get a notification because she did it herself. # Roger doesn't get notified because he is user_type 420 data = dict(first_name="Seconda", an="submit_detail") kwargs = dict(data=urlencode(data)) kwargs['REMOTE_USER'] = '******' url = '/api/pcsw/Clients/{}'.format(second.pk) self.client.force_login(alicia) res = self.client.put(url, **kwargs) self.assertEqual(res.status_code, 200) # self.assertEqual(Message.objects.count(), 2) # self.check_notifications() self.check_notifications(""" =================================================== ======= ============== Sujet Lié à Destinataire --------------------------------------------------- ------- -------------- GÉRARD First (100) a commencé d'attendre caróline caróline =================================================== ======= ============== """) # When a coaching is modified, all active coaches of that # client get a notification. Message.objects.all().delete() data = dict(start_date="02.05.2014", an="grid_put") data.update(mt=51) data.update(mk=second.pk) kwargs = dict(data=urlencode(data)) kwargs['REMOTE_USER'] = '******' self.client.force_login(robin) url = '/api/coachings/CoachingsByClient/{}'.format(second_roger.pk) res = self.client.put(url, **kwargs) self.assertEqual(res.status_code, 200) # self.check_notifications() self.check_notifications(""" ================================== ==================== =========== Subject Controlled by Recipient ---------------------------------- -------------------- ----------- robin a modifié róger / Gérard S *róger / Gérard S* Alicia ================================== ==================== =========== """) # AssignCoach. we are going to Assign caroline as coach for # first client. # Request URL:http://127.0.0.1:8000/api/newcomers/AvailableCoachesByClient/5?_dc=1469707129689&fv=EVERS%20Eberhart%20(127)%20assigned%20to%20Hubert%20Huppertz%20&fv=EVERS%20Eberhart%20(127)%20is%20now%20coached%20by%20Hubert%20Huppertz%20for%20Laufende%20Beihilfe.&fv=false&mt=48&mk=127&an=assign_coach&sr=5 # Request Method:GET # fv:EVERS Eberhart (127) assigned to Hubert Huppertz # fv:EVERS Eberhart (127) is now coached by Hubert Huppertz for Laufende Beihilfe. # fv:false # mt:48 # mk:127 # an:assign_coach # sr:5 Message.objects.all().delete() # self.assertEqual(Coaching.objects.count(), 1) # self.check_coachings() self.check_coachings(""" ==== ====================== ============== ============ ========== ========= ID Client Coached from until Coach Primary ---- ---------------------- -------------- ------------ ---------- --------- 1 GÉRARD Seconda (101) 01/05/2013 01/05/2014 caróline No 2 GÉRARD Seconda (101) 02/05/2014 róger No 3 GÉRARD Seconda (101) 20/05/2014 Alicia No ==== ====================== ============== ============ ========== ========= """) self.assertEqual(Note.objects.count(), 0) data = dict(fv=["First GÉRARD assigned to caróline", "Body", 'false'], an="assign_coach") data.update(mt=ContentType.objects.get_for_model(Client).pk) data.update(mk=first.pk) kwargs = dict(data=data) # kwargs = dict(data=urlencode(data)) kwargs['REMOTE_USER'] = '******' self.client.force_login(alicia) url = '/api/newcomers/AvailableCoachesByClient/{}'.format(caroline.pk) res = self.client.get(url, **kwargs) self.assertEqual(res.status_code, 200) self.check_notifications(""" =================================== ======= ============== Sujet Lié à Destinataire ----------------------------------- ------- -------------- First GÉRARD assigned to caróline caróline =================================== ======= ============== """) # self.check_coachings("") self.check_coachings(""" ==== ====================== ======================== ============ ============= ========== ID Bénéficiaire En intervention depuis au Intervenant Primaire ---- ---------------------- ------------------------ ------------ ------------- ---------- 1 GÉRARD Seconda (101) 01/05/2013 01/05/2014 caróline Non 2 GÉRARD Seconda (101) 02/05/2014 róger Non 3 GÉRARD Seconda (101) 20/05/2014 Alicia Non 4 GÉRARD First (100) 22/05/2014 caróline Oui ==== ====================== ======================== ============ ============= ========== """) self.check_notes(""" ==== ======== ==================== =================================== ID Auteur Bénéficiaire Sujet ---- -------- -------------------- ----------------------------------- 1 Alicia GÉRARD First (100) First GÉRARD assigned to caróline ==== ======== ==================== =================================== """) # Mark client as former # Request URL:http://127.0.0.1:8000/api/pcsw/Clients/181?_dc=1469714189945&an=mark_former&sr=181 # Request Method:GET # an:mark_former Message.objects.all().delete() Note.objects.all().delete() data = dict(an="mark_former") kwargs = dict(data=data) # kwargs = dict(data=urlencode(data)) kwargs['REMOTE_USER'] = '******' self.client.force_login(alicia) url = '/api/pcsw/Clients/{}'.format(second.pk) res = self.client.get(url, **kwargs) self.assertEqual(res.status_code, 200) res = AttrDict(json.loads(res.content)) self.assertEqual(res.message, 'This will end 2 coachings of GÉRARD Seconda (101).') self.assertEqual(res.xcallback['title'], "Confirmation") kwargs = dict() kwargs['REMOTE_USER'] = '******' self.client.force_login(alicia) url = '/callbacks/{}/yes'.format(res.xcallback['id']) res = self.client.get(url, **kwargs) self.assertEqual(res.status_code, 200) res = AttrDict(json.loads(res.content)) self.assertEqual( res.message, 'Alicia a classé GÉRARD Seconda (101) comme <b>Ancien</b>.') self.assertTrue(res.success) self.check_notifications(""" =========================================================== ======================== ============== Sujet Lié à Destinataire ----------------------------------------------------------- ------------------------ -------------- Alicia a classé GÉRARD Seconda (101) comme <b>Ancien</b>. *GÉRARD Seconda (101)* róger =========================================================== ======================== ============== """) # check two coachings have now an end_date set: # self.check_coachings() self.check_coachings(""" ==== ====================== ======================== ============ ============= ========== ID Bénéficiaire En intervention depuis au Intervenant Primaire ---- ---------------------- ------------------------ ------------ ------------- ---------- 1 GÉRARD Seconda (101) 01/05/2013 01/05/2014 caróline Non 2 GÉRARD Seconda (101) 02/05/2014 22/05/2014 róger Non 3 GÉRARD Seconda (101) 20/05/2014 22/05/2014 Alicia Non 4 GÉRARD First (100) 22/05/2014 caróline Oui ==== ====================== ======================== ============ ============= ========== """) # self.check_notes() self.check_notes(""" ==== ======== ====================== =========================================================== ID Auteur Bénéficiaire Sujet ---- -------- ---------------------- ----------------------------------------------------------- 2 Alicia GÉRARD Seconda (101) Alicia a classé GÉRARD Seconda (101) comme <b>Ancien</b>. ==== ======== ====================== =========================================================== """) # # RefuseClient # Message.objects.all().delete() Note.objects.all().delete() self.create_obj(Coaching, client=first, start_date=i2d(20130501), user=roger) first.client_state = ClientStates.newcomer first.save() data = dict(fv=["20", ""], an="refuse_client") kwargs = dict(data=data) # kwargs = dict(data=urlencode(data)) kwargs['REMOTE_USER'] = '******' self.client.force_login(alicia) url = '/api/pcsw/Clients/{}'.format(first.pk) res = self.client.get(url, **kwargs) self.assertEqual(res.status_code, 200) # self.check_notifications("") #if six.PY2: self.check_notifications(""" ========================================================= ====================== ============== Sujet Lié à Destinataire --------------------------------------------------------- ---------------------- -------------- Alicia a classé GÉRARD First (100) comme <b>Refusé</b>. *GÉRARD First (100)* caróline Alicia a classé GÉRARD First (100) comme <b>Refusé</b>. *GÉRARD First (100)* róger ========================================================= ====================== ============== """) # self.check_notes() self.check_notes(""" ==== ======== ==================== ========================================================= ID Auteur Bénéficiaire Sujet ---- -------- -------------------- --------------------------------------------------------- 3 Alicia GÉRARD First (100) Alicia a classé GÉRARD First (100) comme <b>Refusé</b>. ==== ======== ==================== ========================================================= """) # When a note is created, all active coaches of that # client get a notification. Message.objects.all().delete() data = dict() data.update(mt=51) data.update(mk=second.pk) data.update(an='submit_insert') data.update(subject="test", projectHidden=second.pk) kwargs = dict(data=data) kwargs['REMOTE_USER'] = '******' self.client.force_login(alicia) url = '/api/notes/NotesByProject/{}'.format(second.pk) res = self.client.post(url, **kwargs) self.assertEqual(res.status_code, 200) res = AttrDict(json.loads(res.content)) self.assertEqual(res.data_record['id'], 4) new_note_pk = res.data_record['id'] # self.check_notifications() self.check_notifications(""" ============================== ================== ============== Sujet Lié à Destinataire ------------------------------ ------------------ -------------- Alicia created Event/Note #4 *Observation #4* róger ============================== ================== ============== """) Message.objects.all().delete() data = dict() data.update(mt=51) data.update(mk=second.pk) data.update(an='submit_detail') data.update(subject="test 2", body="<p>Bla bla bla</p>", projectHidden=second.pk) kwargs = dict(data=urlencode(data)) # kwargs = dict(data=data) kwargs['REMOTE_USER'] = '******' self.client.force_login(alicia) url = '/api/notes/NotesByProject/{}'.format(new_note_pk) res = self.client.put(url, **kwargs) self.assertEqual(res.status_code, 200) # self.check_notifications() # self.check_notifications("Aucun enregistrement") self.check_notifications(""" =============================== ================== ============== Sujet Lié à Destinataire ------------------------------- ------------------ -------------- Alicia modified Event/Note #4 *Observation #4* róger =============================== ================== ============== """) self.assertEqual(Message.objects.count(), 1) msg = Message.objects.all()[0] # print msg.body self.assertEquivalent( msg.body, """ <div><p>Subject: test 2<br/>Client: [client 101] (Seconda GÉRARD)</p><p>Alicia modified [note 4] (test 2):</p><ul><li><b>Body</b> : 1 lines added</li><li><b>Subject</b> : test --> test 2</li></ul></div> """)
def card2client(self, data): """Convert the data coming from the card into database fields to be stored in the card holder. """ countries = dd.resolve_app('countries', strict=True) kw = dict() raw_data = data['card_data'] if not '\n' in raw_data: # a one-line string means that some error occured (e.g. no # card in reader). of course we want to show this to the # user. raise Warning(raw_data) #~ print cd data = AttrDict(yaml.load(raw_data)) #~ raise Exception("20131108 cool: %s" % cd) kw.update(national_id=ssin.format_ssin(str(data.nationalNumber))) kw.update(first_name=data.firstName or '') kw.update(middle_name=data.middleName or '') kw.update(last_name=data.name or '') card_number = str(data.cardNumber) if data.photo: if not card_number: raise Exception("20150730 photo data but no card_number ") fn = get_image_path(card_number) if fn.exists(): logger.warning("Overwriting existing image file %s.", fn) try: fp = file(fn, 'wb') fp.write(base64.b64decode(data.photo)) fp.close() except IOError as e: logger.warning("Failed to store image file %s : %s", fn, e) #~ print 20121117, repr(data['picture']) #~ kw.update(picture_data_encoded=data['picture']) if isinstance(data.dateOfBirth, basestring): data.dateOfBirth = IncompleteDate(*data.dateOfBirth.split('-')) kw.update(birth_date=data.dateOfBirth) kw.update(card_valid_from=data.cardValidityDateBegin) kw.update(card_valid_until=data.cardValidityDateEnd) kw.update(card_number=card_number) kw.update(card_issuer=data.cardDeliveryMunicipality) if data.nobleCondition: kw.update(noble_condition=data.nobleCondition) if data.streetAndNumber: # kw.update(street=data.streetAndNumber) kw = street2kw(data.streetAndNumber, **kw) if data.zip: kw.update(zip_code=str(data.zip)) if data.placeOfBirth: kw.update(birth_place=data.placeOfBirth) pk = data.reader.upper() msg1 = "BeIdReadCardToClientAction %s" % kw.get('national_id') country = countries.Country.objects.get(isocode=pk) kw.update(country=country) if data.municipality: kw.update(city=countries.Place.lookup_or_create( 'name', data.municipality, country=country)) def sex2gender(sex): if sex == 'MALE': return dd.Genders.male if sex == 'FEMALE': return dd.Genders.female logger.warning("%s : invalid gender code %r", msg1, sex) kw.update(gender=sex2gender(data.gender)) def doctype2cardtype(dt): #~ if dt == 1: return BeIdCardTypes.get_by_value("1") rv = BeIdCardTypes.get_by_value(str(dt)) # logger.info("20130103 documentType %r --> %r", dt, rv) return rv kw.update(card_type=doctype2cardtype(data.documentType)) if config.data_collector_dir: logger.info("Gonna write raw eid card data: %r", raw_data) fn = os.path.join( config.data_collector_dir, card_number + '.txt') file(fn, "w").write(raw_data.encode('utf-8')) logger.info("Wrote eid card data to file %s", fn) return kw
def setup(self, known_values=None, param_values=None, action_param_values={}, **kw): BaseRequest.setup(self, **kw) #~ 20120111 #~ self.known_values = known_values or self.report.known_values #~ if self.report.known_values: #~ d = dict(self.report.known_values) kv = dict() for k, v in self.actor.known_values.items(): kv.setdefault(k, v) if known_values: kv.update(known_values) self.known_values = kv request = self.request if self.actor.parameters is not None: pv = self.actor.param_defaults(self) for k in pv.keys(): if not k in self.actor.parameters: raise Exception( "%s.param_defaults() returned invalid keyword %r" % (self.actor, k)) # New since 20120913. E.g. newcomers.Newcomers is a # simple pcsw.Clients with # known_values=dict(client_state=newcomer) and since there # is a parameter `client_state`, we override that # parameter's default value. for k, v in self.known_values.items(): if k in pv: pv[k] = v # New since 20120914. MyClientsByGroup has a `group` as # master, this must also appear as `group` parameter # value. Lino now understands tables where the master_key # is also a parameter. if self.actor.master_key is not None: if self.actor.master_key in pv: pv[self.actor.master_key] = self.master_instance if param_values is None: if request is not None: ps = self.actor.params_layout.params_store if ps is not None: pv.update(ps.parse_params(request)) else: for k in param_values.keys(): if not k in pv: raise Exception( "Invalid key '%s' in param_values of %s " "request (possible keys are %s)" % (k, self.actor, pv.keys())) pv.update(param_values) self.param_values = AttrDict(**pv) action = self.bound_action.action if action.parameters is not None: apv = action.action_param_defaults(self, None) if request is not None: apv.update( action.params_layout.params_store.parse_params(request)) self.action_param_values = AttrDict(**apv) self.set_action_param_values(**action_param_values) self.bound_action.setup_action_request(self)
def card2client(self, data): """Convert the data coming from the card into database fields to be stored in the card holder. """ countries = dd.resolve_app('countries', strict=True) kw = dict() raw_data = data['card_data'] if not '\n' in raw_data: # a one-line string means that some error occured (e.g. no # card in reader). of course we want to show this to the # user. raise Warning(raw_data) #~ print cd data = AttrDict(yaml.load(raw_data)) #~ raise Exception("20131108 cool: %s" % cd) kw.update(national_id=ssin.format_ssin(str(data.nationalNumber))) kw.update(first_name=data.firstName or '') kw.update(middle_name=data.middleName or '') kw.update(last_name=data.name or '') card_number = str(data.cardNumber) if data.photo: if not card_number: raise Exception("20150730 photo data but no card_number ") fn = get_image_path(card_number) if fn.exists(): logger.warning("Overwriting existing image file %s.", fn) try: fp = file(fn, 'wb') fp.write(base64.b64decode(data.photo)) fp.close() except IOError as e: logger.warning("Failed to store image file %s : %s", fn, e) #~ print 20121117, repr(data['picture']) #~ kw.update(picture_data_encoded=data['picture']) if isinstance(data.dateOfBirth, basestring): data.dateOfBirth = IncompleteDate(*data.dateOfBirth.split('-')) kw.update(birth_date=data.dateOfBirth) kw.update(card_valid_from=data.cardValidityDateBegin) kw.update(card_valid_until=data.cardValidityDateEnd) kw.update(card_number=card_number) kw.update(card_issuer=data.cardDeliveryMunicipality) if data.nobleCondition: kw.update(noble_condition=data.nobleCondition) if data.streetAndNumber: # kw.update(street=data.streetAndNumber) kw = street2kw(data.streetAndNumber, **kw) if data.zip: kw.update(zip_code=str(data.zip)) if data.placeOfBirth: kw.update(birth_place=data.placeOfBirth) pk = data.reader.upper() msg1 = "BeIdReadCardToClientAction %s" % kw.get('national_id') country = countries.Country.objects.get(isocode=pk) kw.update(country=country) if data.municipality: kw.update(city=countries.Place.lookup_or_create( 'name', data.municipality, country=country)) def sex2gender(sex): if sex == 'MALE': return dd.Genders.male if sex == 'FEMALE': return dd.Genders.female logger.warning("%s : invalid gender code %r", msg1, sex) kw.update(gender=sex2gender(data.gender)) def doctype2cardtype(dt): #~ if dt == 1: return BeIdCardTypes.get_by_value("1") rv = BeIdCardTypes.get_by_value(str(dt)) # logger.info("20130103 documentType %r --> %r", dt, rv) return rv kw.update(card_type=doctype2cardtype(data.documentType)) if config.data_collector_dir: logger.info("Gonna write raw eid card data: %r", raw_data) fn = os.path.join(config.data_collector_dir, card_number + '.txt') file(fn, "w").write(raw_data.encode('utf-8')) logger.info("Wrote eid card data to file %s", fn) return kw
def card2client(self, data): "does the actual conversion" countries = dd.resolve_app('countries', strict=True) kw = dict() raw_data = data['card_data'] if not '\n' in raw_data: # a one-line string means that some error occured (e.g. no # card in reader). of course we want to show this to the # user. raise Warning(raw_data) #~ print cd data = AttrDict(yaml.load(raw_data)) #~ raise Exception("20131108 cool: %s" % cd) kw.update(national_id=ssin.format_ssin(str(data.nationalNumber))) kw.update(first_name=join_words( data.firstName, data.middleName)) kw.update(last_name=data.name) card_number = str(data.cardNumber) if data.photo: fn = config.card_number_to_picture_file(card_number) if os.path.exists(fn): logger.warning("Overwriting existing image file %s.", fn) fp = file(fn, 'wb') fp.write(base64.b64decode(data.photo)) fp.close() #~ print 20121117, repr(data['picture']) #~ kw.update(picture_data_encoded=data['picture']) if isinstance(data.dateOfBirth, basestring): data.dateOfBirth = IncompleteDate(*data.dateOfBirth.split('-')) kw.update(birth_date=data.dateOfBirth) kw.update(card_valid_from=data.cardValidityDateBegin) kw.update(card_valid_until=data.cardValidityDateEnd) kw.update(card_number=card_number) kw.update(card_issuer=data.cardDeliveryMunicipality) if data.nobleCondition: kw.update(noble_condition=data.nobleCondition) kw.update(street=data.streetAndNumber) #~ kw.update(street_no=data['streetNumber']) #~ kw.update(street_box=data['boxNumber']) if True: # kw['street'] and not (kw['street_no'] or kw['street_box']): kw = street2kw(kw['street'], **kw) kw.update(zip_code=str(data.zip)) if data.placeOfBirth: kw.update(birth_place=data.placeOfBirth) pk = data.reader.upper() msg1 = "BeIdReadCardToClientAction %s" % kw.get('national_id') #~ try: country = countries.Country.objects.get(isocode=pk) kw.update(country=country) #~ except countries.Country.DoesNotExist,e: #~ except Exception,e: #~ logger.warning("%s : no country with code %r",msg1,pk) #~ BE = countries.Country.objects.get(isocode='BE') #~ fld = countries.Place._meta.get_field() kw.update(city=countries.Place.lookup_or_create( 'name', data.municipality, country=country)) def sex2gender(sex): if sex == 'MALE': return dd.Genders.male if sex == 'FEMALE': return dd.Genders.female logger.warning("%s : invalid gender code %r", msg1, sex) kw.update(gender=sex2gender(data.gender)) def doctype2cardtype(dt): #~ if dt == 1: return BeIdCardTypes.get_by_value("1") rv = BeIdCardTypes.get_by_value(str(dt)) # logger.info("20130103 documentType %r --> %r", dt, rv) return rv kw.update(card_type=doctype2cardtype(data.documentType)) if config.data_collector_dir: fn = os.path.join( config.data_collector_dir, card_number + '.txt') file(fn, "w").write(raw_data) logger.info("Wrote eid card data to file %s", fn) return kw
def test01(self): # is it the right settings module? self.assertEqual(os.environ["DJANGO_SETTINGS_MODULE"], "lino_welfare.projects.std.settings.demo") self.assertEqual( settings.MIDDLEWARE_CLASSES, ( "django.middleware.common.CommonMiddleware", "django.middleware.locale.LocaleMiddleware", "lino.core.auth.RemoteUserMiddleware", "lino.utils.ajax.AjaxExceptionResponse", ), ) u = users.User(username="******", profile=UserTypes.admin, language="en") u.save() be = countries.Country(name="Belgium", isocode="BE") be.save() kw = dict() # kw.update(card_number="123456789") # kw.update(national_id="680601 053-29") kw.update(id=116) kw.update(first_name="Jean") kw.update(middle_name="Jacques") kw.update(last_name="Jeffin") obj = pcsw.Client(**kw) obj.full_clean() obj.save() from lino_xl.lib.households.fixtures.std import objects for o in objects(): o.save() # FIRST TEST : helped me to understand a problem on 20150130 # ("Submitting an ActionFormPanel no longer forwards # `param_values`"). Since the problem was caused by # Javascript code in :xfile:`linoweb.js`, it cannot # actually reproduce the problem (that would # require a Javascript testing framework). # Reception --> Clients --> Detail on client 116 url = "/api/reception/Clients/116?" # url += "pv=&pv=&pv=&pv=&pv=false&pv=&pv=&pv=&pv=&pv=&pv=10&pv=false" url += "&an=detail&rp=ext-comp-1359&fmt=json" response = self.client.get(url, REMOTE_USER="******") result = self.check_json_result(response, "navinfo data disable_delete id title") fieldname = "MembersByPerson" html = result["data"][fieldname] soup = BeautifulSoup(html) links = soup.find_all("a") self.assertEqual(len(links), 6) self.assertEqual(links[0].string, "Married couple") self.assertEqual(links[1].get_text(), "Divorced couple") js = links[0]["href"] # javascript:Lino.contacts.Persons.create_household.run(\ # "ext-comp-1359",{ # "field_values": { "head": "JEFFIN Jean (116)", "headHidden": # 116, "typeHidden": 1, "partner": null, "partnerHidden": # null, "type": "Married" }, "param_values": { # "also_obsolete": false, "gender": null, "genderHidden": null # }, "base_params": { } }) start = "javascript:Lino.contacts.Persons.create_household." 'run("ext-comp-1359",' self.assertEqual(js.startswith(start), True) js = js[len(start) : -1] d = AttrDict(json.loads(js)) self.assertEqual(" ".join(d.keys()), "field_values param_values base_params") self.assertEqual(len(d.field_values), 6) self.assertEqual(len(d.param_values), 3) self.assertEqual(len(d.base_params), 0) fv = AttrDict(d.field_values) self.assertEqual(fv.head, "JEFFIN Jean (116)") pv = AttrDict(d.param_values) self.assertEqual(pv.also_obsolete, False) self.assertEqual(pv.gender, None) self.assertEqual(pv.genderHidden, None) # When user klicks OK: url = "/api/contacts/Persons/116" url += "?fv=&fv=1&fv=116&an=create_household" # The 20150130 problem was because the ActionFormPanel added # param_values. When klicking OK, it sometimes added the # following: if False: # before 20150130 url += "&pv=&pv=&pv=&pv=&pv=false&pv=&pv=&pv=&pv=&pv=&pv=10&pv=false" url += "&sr=116" response = self.client.get(url, REMOTE_USER="******") result = self.check_json_result(response, "message eval_js success refresh_all close_window")