def setup_client_workflow(sender=None, **kw): """Set up workflow for :class:`ClientStates <lino_welfare.modlib.pcsw.choicelists.ClientStates>`. """ # ClientStates.refused.add_transition(RefuseClient) # ClientStates.former.add_transition(MarkClientFormer) ClientStates.newcomer.add_transition( required_states='former', required_roles=dd.required(NewcomersAgent))
courses.CourseRequestsByPerson """, label=_("Languages")) competences = dd.Panel(""" cv.SkillsByPerson cv.SoftSkillsByPerson skills cv.ObstaclesByPerson obstacles badges.AwardsByHolder """, label=_("Competences"), required_roles=dd.required(IntegrationAgent)) contracts = dd.Panel(""" isip.ContractsByClient jobs.CandidaturesByPerson jobs.ContractsByClient """, label=_("Contracts")) if settings.SITE.is_installed('cbss'): ClientDetail.main += ' cbss' ClientDetail.cbss = dd.Panel(""" cbss_identify_person cbss_manage_access cbss_retrieve_ti_groups cbss_summary """, label=_("CBSS"), required_roles=dd.required(SocialAgent)) Clients.detail_layout = ClientDetail() ClientContactTypes.detail_layout = """ id name can_refund is_bailiff contacts.PartnersByClientContactType pcsw.ClientContactsByType """ ClientContactTypes.column_names = "id name can_refund is_bailiff"
class PropTypes(dd.Table): required_roles = dd.required(dd.SiteStaff) model = PropType detail_layout = """
class MyComments(My, Comments): required_roles = dd.required(OfficeUser) auto_fit_column_widths = True order_by = ["modified"] column_names = "modified short_text owner *"
class CommentsByX(Comments): required_roles = dd.required(OfficeUser) order_by = ["-created"]
class AllExcerpts(Excerpts): required_roles = dd.required(SiteAdmin, OfficeStaff) column_names = ("id excerpt_type owner project " "company language build_time *")
class Languages(dd.Table): model = 'languages.Language' required_roles = dd.required(OfficeUser)
class DebtorsCreditors(dd.VirtualTable): """ Abstract base class for different tables showing a list of partners with the following columns: partner due_date balance actions """ required_roles = dd.required(AccountingReader) auto_fit_column_widths = True column_names = "age due_date partner partner_id balance vouchers" slave_grid_format = 'html' abstract = True parameters = mixins.Today() # params_layout = "today" d_or_c = NotImplementedError @classmethod def rowmvtfilter(self, row): raise NotImplementedError() @classmethod def get_data_rows(self, ar): rows = [] mi = ar.master_instance if mi is None: # called directly from main menu if ar.param_values is None: return rows end_date = ar.param_values.today else: # called from Situation report end_date = mi.today qs = rt.modules.contacts.Partner.objects.order_by('name') for row in qs: row._balance = ZERO row._due_date = None row._expected = tuple( get_due_movements(self.d_or_c, partner=row, value_date__lte=end_date)) for dm in row._expected: row._balance += dm.balance if dm.due_date is not None: if row._due_date is None or row._due_date > dm.due_date: row._due_date = dm.due_date # logger.info("20140105 %s %s", row, dm) if row._balance > ZERO: rows.append(row) def k(a): return a._due_date rows.sort(key=k) return rows # @dd.displayfield(_("Partner")) # def partner(self, row, ar): # return ar.obj2html(row) @dd.virtualfield(models.ForeignKey('contacts.Partner')) def partner(self, row, ar): return row @dd.virtualfield(models.IntegerField(_("ID"))) def partner_id(self, row, ar): return row.pk @dd.virtualfield(dd.PriceField(_("Balance"))) def balance(self, row, ar): return row._balance @dd.virtualfield(models.DateField(_("Due date"))) def due_date(self, row, ar): return row._due_date @dd.virtualfield(models.IntegerField(_("Age"))) def age(self, row, ar): dd = ar.param_values.today - row._due_date return dd.days @dd.displayfield(_("Vouchers")) def vouchers(self, row, ar): matches = [dm.match for dm in row._expected] return E.span(', '.join(matches))
class ExpectedMovements(dd.VirtualTable): """ A virtual table of :class:`DueMovement` rows, showing all "expected" "movements (payments)". Subclassed by :class:`lino_cosi.lib.finan.models.SuggestionsByVoucher`. """ row_height = 4 required_roles = dd.required(AccountingReader) label = _("Debts") icon_name = 'book_link' #~ column_names = 'match due_date debts payments balance' column_names = 'due_date:15 balance debts payments' auto_fit_column_widths = True # variable_row_height = True parameters = dd.ParameterPanel( date_until=models.DateField(_("Date until"), blank=True, null=True), trade_type=TradeTypes.field(blank=True), from_journal=dd.ForeignKey('ledger.Journal', blank=True), for_journal=dd.ForeignKey('ledger.Journal', blank=True, verbose_name=_("Clearable by")), account=dd.ForeignKey('accounts.Account', blank=True), partner=dd.ForeignKey('contacts.Partner', blank=True), project=dd.ForeignKey(dd.plugins.ledger.project_model, blank=True), ) params_layout = "trade_type date_until from_journal " \ "for_journal project partner account" @classmethod def get_dc(cls, ar=None): return DEBIT @classmethod def get_data_rows(cls, ar, **flt): #~ if ar.param_values.journal: #~ pass pv = ar.param_values # if pv is None: # raise Exception("No pv in %s" % ar) if pv.trade_type: flt.update(account=pv.trade_type.get_partner_account()) if pv.partner: flt.update(partner=pv.partner) if pv.account: flt.update(account=pv.account) if pv.project: flt.update(project=pv.project) if pv.date_until is not None: flt.update(value_date__lte=pv.date_until) if pv.for_journal is not None: accounts = rt.modules.accounts.Account.objects.filter( matchrule__journal=pv.for_journal).distinct() flt.update(account__in=accounts) if pv.from_journal is not None: flt.update(voucher__journal=pv.from_journal) return get_due_movements(cls.get_dc(ar), **flt) @classmethod def get_pk_field(self): return rt.modules.ledger.Movement._meta.pk @classmethod def get_row_by_pk(cls, ar, pk): # for i in ar.data_iterator: # if i.id == pk: # return i # raise Exception("Not found: %s in %s" % (pk, ar)) mvt = rt.modules.ledger.Movement.objects.get(pk=pk) dm = DueMovement(cls.get_dc(ar), mvt) dm.collect_all() return dm @dd.displayfield(_("Info")) def info(self, row, ar): elems = [] if row.project: elems.append(ar.obj2html(row.project)) if row.partner: elems.append(ar.obj2html(row.partner)) # elems.append(row.partner.address) if row.bank_account: elems.append(ar.obj2html(row.bank_account)) if row.account: elems.append(ar.obj2html(row.account)) # return E.span(*join_elems(elems, ' / ')) return E.span(*join_elems(elems, E.br)) # return E.span(*elems) @dd.displayfield(_("Match")) def match(self, row, ar): return row.match @dd.virtualfield( models.DateField( _("Due date"), help_text=_("Due date of the eldest debt in this match group"))) def due_date(self, row, ar): return row.due_date @dd.displayfield(_("Debts"), help_text=_("List of invoices in this match group")) def debts(self, row, ar): return E.span(*join_elems([ # E.p(...) until 20150128 ar.obj2html(i.voucher.get_mti_leaf()) for i in row.debts ])) @dd.displayfield(_("Payments"), help_text=_("List of payments in this match group")) def payments(self, row, ar): return E.span(*join_elems([ # E.p(...) until 20150128 ar.obj2html(i.voucher.get_mti_leaf()) for i in row.payments ])) @dd.virtualfield(dd.PriceField(_("Balance"))) def balance(self, row, ar): return row.balance @dd.virtualfield(dd.ForeignKey('contacts.Partner')) def partner(self, row, ar): return row.partner @dd.virtualfield(dd.ForeignKey(dd.plugins.ledger.project_model)) def project(self, row, ar): return row.project @dd.virtualfield(dd.ForeignKey('accounts.Account')) def account(self, row, ar): return row.account @dd.virtualfield( dd.ForeignKey('sepa.Account', verbose_name=_("Bank account"))) def bank_account(self, row, ar): return row.bank_account
class MyTextFieldTemplates(TextFieldTemplates, ByUser): required_roles = dd.required(OfficeUser)
class CivilStates(dd.ChoiceList): """The global list of **civil states** that a client can have. This is the list of choices for the :attr:`civil_state <lino_welfare.modlib.pcsw.models.Client.civil_state>` field of a :class:`Client <lino_welfare.modlib.pcsw.models.Client>`. **The four official civil states** according to Belgian law are: .. attribute:: single célibataire : vous n’avez pas de partenaire auquel vous êtes officiellement lié .. attribute:: married marié(e) : vous êtes légalement marié .. attribute:: widowed veuf (veuve) / Verwitwet : vous êtes légalement marié mais votre partenaire est décédé .. attribute:: divorced divorcé(e) (Geschieden) : votre mariage a été juridiquement dissolu **Some institutions define additional civil states** for people who are officially still married but at different degrees of separation: .. attribute:: de_facto_separated De facto separated (Séparé de fait, faktisch getrennt) Des conjoints sont séparés de fait lorsqu'ils ne respectent plus le devoir de cohabitation. Leur mariage n'est cependant pas dissous. La notion de séparation de fait n'est pas définie par la loi. Toutefois, le droit en tient compte dans différents domaines, par exemple en matière fiscale ou en matière de sécurité sociale (assurance maladie invalidité, allocations familiales, chômage, pension, accidents du travail, maladies professionnelles). .. attribute:: separated Legally separated, aka "Separated as to property" (Séparé de corps et de biens, Getrennt von Tisch und Bett) La séparation de corps et de biens est une procédure judiciaire qui, sans dissoudre le mariage, réduit les droits et devoirs réciproques des conjoints. Le devoir de cohabitation est supprimé. Les biens sont séparés. Les impôts sont perçus de la même manière que dans le cas d'un divorce. Cette procédure est devenue très rare. **Another unofficial civil state** (but relevant in certain situations) is: .. attribute:: cohabitating Cohabitating (cohabitant, zusammenlebend) Vous habitez avec votre partenaire et c’est reconnu légalement. Sources for above: `belgium.be <http://www.belgium.be/fr/famille/couple/divorce_et_separation/separation_de_fait/>`__, `gouv.qc.ca <http://www4.gouv.qc.ca/EN/Portail/Citoyens/Evenements/separation-divorce/Pages/separation-fait.aspx>`__, `wikipedia.org <https://en.wikipedia.org/wiki/Cohabitation>`__ """ required_roles = dd.required(dd.SiteStaff) verbose_name = _("Civil state") verbose_name_plural = _("Civil states") @classmethod def old2new(cls, old): """ **Migration rules** (October 2015) to remove some obsolete choices: - 13 (Single cohabitating) becomes :attr:`cohabitating` - 18 (Single with child) becomes :attr:`single` - 21 (Married (living alone)) becomes :attr:`separated_de_facto` - 22 (Married (living with another partner)) becomes :attr:`separated_de_facto` - 33 (Widow cohabitating) becomes :attr:`widowed` """ if old == '13': return cls.cohabitating if old == '18': return cls.single if old == '21': return cls.separated_de_facto if old == '22': return cls.separated_de_facto if old == '33': return cls.widowed return cls.get_by_value(old) @classmethod def to_python(cls, value): """This will call :meth:`old2new` when loading data from previous version. Can be removed when all production sites have been migrated. """ if value: return cls.old2new(value) return None
class UploadAreas(dd.ChoiceList): required_roles = dd.required(OfficeStaff) verbose_name = _("Upload Area") verbose_name_plural = _("Upload Areas")