Пример #1
0
class Attendee(models.Model):
    """Calendar Attendee Information"""
    STATUS = (
        ('action', _('Needs Action')),
        ('uncertain', _('Uncertain')),
        ('declined', _('Declined')),
        ('accepted', _('Accepted')),
    )

    status = models.ChoiceField(
        STATUS, readonly=True, default='needs-action',
        help_text="Status of the attendee's participation"
    )
    partner = models.ForeignKey('res.partner', 'Contact', readonly=True)
    email = models.EmailField(verbose_name=_('Email'), help_text="Email of Invited Person")
    availability = models.ChoiceField(
        (('free', _('Free')), ('busy', _('Busy'))), verbose_name=_('Free/Busy'), readonly=True
    )
    access_token = models.CharField(64, 'Invitation Token')
    event = models.ForeignKey('calendar.event', _('Meeting linked'), ondelete=models.CASCADE)

    class Meta:
        name = 'calendar.attendee'
        verbose_name = 'Calendar Attendee Information'
        verbose_name_plural = 'Calendar Attendee Informations'
Пример #2
0
class Contacts(models.Model):
    user = models.ForeignKey('auth.user', null=False, default=get_current_user)
    partner = models.ForeignKey('res.partner', verbose_name=_('Partner'))
    active = models.BooleanField(default=True, verbose_name=_('Active'))

    class Meta:
        name = 'calendar.contacts'
Пример #3
0
Файл: ui.py Проект: katrid/orun
class CustomView(models.Model):
    user = models.ForeignKey('auth.user', null=False)
    view = models.ForeignKey(View, null=False)
    content = models.TextField()

    class Meta:
        name = 'ui.view.custom'
Пример #4
0
class UserActionCounter(models.Model):
    """
    Ranking the number of times that an action is accessed by user on Admin UI
    """
    user = models.ForeignKey('auth.user', null=False, db_index=True)
    action = models.ForeignKey('ui.action',
                               null=False,
                               on_delete=models.DB_CASCADE)
    counter = models.PositiveIntegerField(default=0)

    class Meta:
        log_changes = False
        name = 'ui.admin.user.action.counter'

    @classmethod
    def log(cls, user, action):
        """
        Log a new entry to user latest action access
        :param user:
        :param action:
        :return:
        """
        counter = cls.objects.get_or_create(user=user, action=action)
        counter.counter += 1
        counter.save()
Пример #5
0
class UserHomepage(models.Model):
    homepage = models.ForeignKey(Homepage, null=False, on_delete=models.DB_CASCADE)
    user = models.ForeignKey('auth.user', null=False, on_delete=models.DB_CASCADE)
    content = models.TextField()

    class Meta:
        name = 'ui.user.homepage'
        unique_together = ('homepage', 'user')
Пример #6
0
class UserReport(models.Model):
    report = models.ForeignKey(ReportAction)
    company = models.ForeignKey('res.company')
    public = models.BooleanField(default=True)
    params = models.TextField()

    class Meta:
        name = 'usr.report'
Пример #7
0
class WindowActionView(models.Model):
    window_action = models.ForeignKey(WindowAction, null=False)
    sequence = models.SmallIntegerField()
    view = models.ForeignKey('ui.view')
    view_mode = models.SelectionField(WindowAction.VIEW_MODE, label=_('View Type'))

    class Meta:
        name = 'ui.action.window.view'
        title_field = 'view'
Пример #8
0
class CashboxLine(models.Model):
    coin_value = models.FloatField(verbose_name=_('Coin/Bill Value'), null=False)
    number = models.IntegerField(verbose_name=_('#Coins/Bills'))
    # subtotal = models.FloatField()
    cashbox = models.ForeignKey('account.bank.statement.cashbox', verbose_name=_('Cashbox'))
    currency = models.ForeignKey('res.currency', proxy='cashbox.currency')

    class Meta:
        name = 'account.cashbox.line'
Пример #9
0
class ServerAction(Action):
    sequence = models.IntegerField(default=5)
    model = models.ForeignKey('content.type', null=False)
    code = models.TextField(label=_('Python Code'))
    actions = models.ManyToManyField('self')
    target_model = models.ForeignKey('content.type')
    target_field = models.ForeignKey('content.field')
    lines = models.OneToManyField('ui.action.server.line')

    class Meta:
        name = 'ui.action.server'
Пример #10
0
class ServerActionLine(models.Model):
    server_action = models.ForeignKey(ServerAction, null=False, on_delete=models.CASCADE)
    field = models.ForeignKey('content.field')
    value = models.TextField()
    type = models.SelectionField(
        (
            ('value', _('Value')),
            ('expr', _('Python Expression')),
        ), label=_('Evaluation Type')
    )

    class Meta:
        name = 'ui.action.server.line'
Пример #11
0
class LogEntry(models.Model):
    """
    Log entries on the internal database logging
    """
    user = models.ForeignKey('auth_user', null=False, db_index=True)
    action = models.ForeignKey('ui.action')  # optional ui action
    object_id = models.BigIntegerField()
    content_type = models.ForeignKey('content.type', on_delete=models.SET_NULL)
    content_object = models.CharField(200)
    change_message = models.TextField()

    class Meta:
        log_changes = False
        name = 'ui.admin.log'
Пример #12
0
Файл: ui.py Проект: katrid/orun
class Filter(models.Model):
    name = models.CharField(256, null=False, verbose_name=_('Name'))
    user = models.ForeignKey('auth.user', on_delete=models.CASCADE)
    domain = models.TextField()
    context = models.TextField()
    sort = models.TextField()
    params = models.TextField()
    is_default = models.BooleanField(default=False)
    is_shared = models.BooleanField(default=True)
    action = models.ForeignKey('ui.action', verbose_name=_('Action'))
    # query = models.ForeignKey('ir.query')
    active = models.BooleanField(default=True)

    class Meta:
        name = 'ui.filter'
Пример #13
0
class AutoReport(models.Model):
    name = models.CharField(128, null=False)
    model = models.ForeignKey('content.type', null=False)
    content = models.TextField()

    class Meta:
        name = 'ui.report.auto'
Пример #14
0
class ViewAction(Action):
    view = models.ForeignKey('ui.view', label=_('View'))

    class Meta:
        name = 'ui.action.view'

    def _get_info(self, context):
        from orun.contrib.admin.models.ui import View
        res = super()._get_info(context)
        # it's a system class
        if self.qualname:
            admin_class = import_string(self.qualname)
            res.update(admin_class.render(None))
            del res['qualname']
        view = res.get('view')
        if view and view['id']:
            res['template'] = View.objects.get(pk=view['id']).get_content()
        return res

    @api.classmethod
    def get_view(cls, id):
        if isinstance(id, list):
            id = id[0]
        view = apps['ui.view'].objects.get(pk=id)
        return {
            'content': view.render({}),
            'type': view.view_type,
        }
Пример #15
0
class ClientAction(Action):
    tag = models.CharField(512)
    target = models.SelectionField(
        (
            ('current', 'Current Window'),
            ('new', 'New Window'),
            ('fullscreen', 'Full Screen'),
            ('main', 'Main Action of Current Window'),
        ), default='current',
    )
    model_name = models.CharField(label=_('Model'))
    context = models.TextField()
    params = models.TextField()
    view = models.ForeignKey('ui.view')

    class Meta:
        name = 'ui.action.client'

    @api.method(request=True)
    def get_view(self, id, request):
        vw = self.objects.get(id)
        if vw.view:
            return {
                'content': vw.view.render({}),
            }
Пример #16
0
class HomepageGroup(models.Model):
    name = models.CharField(128)
    group = models.ForeignKey('auth.group')
    info = models.JSONField()

    class Meta:
        name = 'ui.homepage.group'
Пример #17
0
class Action(models.Model):
    name = models.CharField(128, _('Name'), null=False, translate=True)
    action_type = models.CharField(32, _('Action Type'), null=False)
    usage = models.TextField(label=_('Usage'))
    description = models.TextField(label=_('Description'))
    # external_id = models.CharField(label=_('External ID'), getter='get_external_id')
    groups = models.ManyToManyField('auth.group')
    binding_model = models.ForeignKey('content.type', on_delete=models.CASCADE)
    binding_type = models.SelectionField(
        (
            ('action', _('Action')),
            ('print', _('Print')),
        ),
        default='action',
    )
    multiple = models.BooleanField(default=False, label='Restrict to lists')
    qualname = models.CharField(help_text='System qualified name')

    class Meta:
        name = 'ui.action'
        field_groups = {
            'list_fields': ['name', 'action_type', 'usage']
        }

    def save(self, *args, **kwargs):
        if not self.action_type:
            self.action_type = self.__class__._meta.name
        super(Action, self).save(*args, **kwargs)

    def get_action(self):
        return apps[self.action_type].objects.get(pk=self.pk)

    @api.classmethod
    def load(cls, name_or_id, context=None):
        try:
            name_or_id = int(name_or_id)
        except ValueError:
            if isinstance(name_or_id, str):
                name_or_id = ref(name_or_id)
        info = cls.get(name_or_id).get_action()._get_info(context)
        info['type'] = info.pop('action_type')
        return info

    def execute(self):
        raise NotImplemented()

    @classmethod
    def get_bindings(cls, model):
        r = defaultdict(list)
        # TODO: optimize filter by name (plain query)
        obj = apps['content.type'].objects.get_by_natural_key(model)
        for action in cls.objects.filter(binding_model_id=obj.pk):
            r[action.binding_type].append(action)
        return r

    def _get_info(self, context):
        return self.to_dict(exclude=['groups'])
Пример #18
0
class Stage(models.Model):
    """ Model for case stages. This models the main stages of a document
        management flow. Main CRM objects (leads, opportunities, project
        issues, ...) will now use only stages, instead of state and stages.
        Stages are for example used to display the kanban view of records.
    """
    name = models.CharField(
        128, verbose_name=_('Stage Name'), null=False, translate=True
    )
    sequence = models.IntegerField(
        verbose_name=_('Sequence'), default=1, help_text="Used to order stages. Lower is better."
    )
    probability = models.FloatField(
        verbose_name=_('Probability (%)'), null=False, default=10.0,
        help_text="This percentage depicts the default/average probability of the Case for this stage to be a success")
    on_change = models.BooleanField(
        verbose_name=_('Change Probability Automatically'),
        help_text="Setting this stage will change the probability automatically on the opportunity.")
    requirements = models.TextField(
        verbose_name=_('Requirements'),
        help_text="Enter here the internal requirements for this stage (ex: Offer sent to customer). It will appear as a tooltip over the stage's name."
    )
    team_id = models.ForeignKey(
        'crm.team', verbose_name='Sales Team', ondelete=models.CASCADE,
        help_text='Specific team that uses this stage. Other teams will not be able to see or use this stage.'
    )
    legend_priority = models.TextField(
        verbose_name=_('Priority Management Explanation'), translate=True,
        help_text='Explanation text to help users using the star and priority mechanism on stages or issues that are in this stage.'
    )
    fold = models.BooleanField(
        verbose_name=_('Folded in Pipeline'),
        help_text='This stage is folded in the kanban view when there are no records in that stage to display.'
    )

    # This field for interface only
    team_count = models.IntegerField('team_count', compute='_compute_team_count')

    @api.record
    def default_get(self, fields):
        """ Hack :  when going from the pipeline, creating a stage with a sales team in
            context should not create a stage for the current Sales Team only
        """
        ctx = dict(self.env.context)
        if ctx.get('default_team_id') and not ctx.get('crm_team_mono'):
            ctx.pop('default_team_id')
        return super(Stage, self.with_context(ctx)).default_get(fields)

    @api.records
    def _compute_team_count(self):
        for stage in self:
            stage.team_count = self.env['crm.team'].search_count([])

    class Meta:
        name = "crm.stage"
        verbose_name = "CRM Stages"
        ordering = ('sequence', 'name', 'id')
Пример #19
0
class Rule(models.Model):
    name = models.CharField(128, verbose_name=_('object name'), null=False)
    active = models.BooleanField(default=True)
    content_type = models.ForeignKey('content.type',
                                     null=False,
                                     db_index=True,
                                     on_delete=models.DB_CASCADE)
    groups = models.ManyToManyField('auth.group')
    domain = models.TextField()

    class Meta:
        name = 'ir.rule'
Пример #20
0
class ProductionLot(models.Model):
    name = models.CharField(
        100,
        label=_('Lot/Serial'),
        null=False,
        help_text=_('Unique Lot/Serial Number'),
        default=lambda self: self.env['ir.sequence'].next_by_code(
            'stock.lot.serial'),
    )
    ref = models.CharField(
        100,
        label=_('Internal Reference'),
        help_text=
        _("Internal reference number in case it differs from the manufacturer's lot/serial number"
          ))
    product = models.ForeignKey('product.product',
                                label=_('Product'),
                                null=False,
                                check_company=True,
                                filter=lambda self: self.domain_product_id())
    product_uom = models.ForeignKey('uom.uom',
                                    label=_('Unit of Measure'),
                                    related='product.uom',
                                    stored=True)
    quants = models.OneToManyField('stock.quant', readonly=True)
    product_qty = models.DecimalField(label=_('Quantity'),
                                      getter='get_product_qty')
    description = models.HtmlField(label=_('Description'))
    display_complete = models.BooleanField(getter='get_display_complete')
    company = models.ForeignKey('res.company',
                                label=_('Company'),
                                null=False,
                                stored=True,
                                db_index=True)

    class Meta:
        name = 'stock.production.lot'
        verbose_name = 'Lot/Serial'
Пример #21
0
class Team(models.Model):
    name = models.CharField(100, verbose_name=_('Name'))
    active = models.BooleanField(verbose_name=_('Active'), default=True)
    company = models.ForeignKey('res.company')
    # currency = models.ForeignKey('res.currency')
    user = models.ForeignKey('auth.user', verbose_name=_('Team Leader'))
    members = models.OneToManyField('auth.user', 'sale_team')
    favorite_users = models.ManyToManyField('auth.user')
    color = models.IntegerField()
    team_type = models.ChoiceField(
        (
            ('sales', _('Sales')),
            ('website', _('Website')),
        ),
        default='sales',
        null=False,
        verbose_name=_('Team Type'),
    )

    class Meta:
        name = 'sales.team'
        verbose_name = _('Sales Team')
        verbose_name_plural = _('Sales Teams')
Пример #22
0
class AccountBankStatementLine(models.Model):

    name = models.CharField(verbose_name='Label', null=False)
    date = models.DateField(null=False, default=lambda self: self._context.get('date', models.DateField.context_today(self)))
    amount = models.MonetaryField(currency_field='journal_currency')
    journal_currency = models.ForeignKey(
        'res.currency', verbose_name="Journal's Currency", proxy='statement.currency',
        help_text='Utility field to express amount currency', readonly=True
    )
    partner = models.ForeignKey('res.partner', verbose_name='Partner')
    account_number = models.CharField(verbose_name='Bank Account Number', help_text="Technical field used to store the bank account number before its creation, upon the line's processing")
    bank_account = models.ForeignKey('res.partner.bank', verbose_name='Bank Account', help_text="Bank account that was used in this transaction.")
    account = models.ForeignKey('account.account', verbose_name='Counterpart Account', domain=[('deprecated', '=', False)],
                                 help_text="This technical field can be used at the statement line creation/import time in order to avoid the reconciliation"
                                      " process on it later on. The statement line will simply create a counterpart on this account")
    statement = models.ForeignKey('account.bank.statement', verbose_name='Statement', index=True, null=False, on_delete=models.CASCADE)
    journal = models.ForeignKey('account.journal', proxy='statement.journal', verbose_name='Journal', store=True, readonly=True)
    partner_name = models.CharField(help_text="This field is used to record the third party name when importing bank statement in electronic format,"
                                    " when the partner doesn't exist yet in the database (or cannot be found).")
    ref = models.CharField(verbose_name='Reference')
    note = models.TextField(verbose_name='Notes')
    transaction_type = models.CharField(verbose_name='Transaction Type')
    sequence = models.IntegerField(index=True, help_text="Gives the sequence order when displaying a list of bank statement lines.", default=1)
    company = models.ForeignKey('res.company', proxy='statement.company', verbose_name='Company', store=True, readonly=True)
    journal_entrys = models.OneToManyField('account.move.line', 'statement_line', 'Journal Items', copy=False, readonly=True)
    amount_currency = models.MonetaryField(help_text="The amount expressed in an optional other currency if it is a multi-currency entry.")
    currency = models.ForeignKey('res.currency', verbose_name='Currency', help_text="The optional other currency if it is a multi-currency entry.")
    state = models.ChoiceField(proxy='statement.state', verbose_name='Status', readonly=True)
    move_name = models.CharField(
        verbose_name='Journal Entry Name', readonly=True,
        default=False, copy=False,
        help_text="Technical field holding the number given to the journal entry, automatically set when the statement line is reconciled then stored to set the same number again if the line is cancelled, set to draft and re-processed again."
    )
    
    class Meta:
        name = 'account.bank.statement.line'
        description = _('Bank Statement Line')
        ordering = ('-statement_id', 'date', 'sequence', '-id')
Пример #23
0
class BankStatement(models.Model):
    name = models.CharField(verbose_name='Reference', states={'open': {'readonly': False}}, copy=False, readonly=True)
    reference = models.CharField(verbose_name='External Reference', states={'confirm': {'readonly': False}}, copy=False, readonly=True)
    date = models.DateField(null=False, states={'confirm': {'readonly': True}})
    date_done = models.DateTimeField(verbose_name=_('Closed On'))
    balance_start = models.MonetaryField(verbose_name=_('Starting Balance'), states={'confirm': {'readonly': True}})
    balance_end_real = models.MonetaryField('Ending Balance', states={'confirm': [('readonly', True)]})
    accounting_date = models.DateField(verbose_name="Accounting Date", help_text="If set, the accounting entries created during the bank statement reconciliation process will be created at this date.\n"
                                                                 "This is useful if the accounting period in which the entries should normally be booked is already closed.",
                                  states={'open': [('readonly', False)]}, readonly=True)
    state = models.ChoiceField([('open', 'New'), ('confirm', 'Validated')], verbose_name='Status', null=False, readonly=True, copy=False, default='open')
    currency = models.ForeignKey('res.currency', compute='_compute_currency', verbose_name="Currency")
    journal = models.ForeignKey('account.journal', verbose_name='Journal', null=False, states={'confirm': [('readonly', True)]}, default=_default_journal)
    journal_type = models.ChoiceField(proxy='journal.type', help_text="Technical field used for usability purposes")
    company = models.ForeignKey(
        'res.company', proxy='journal.company', verbose_name='Company', store=True, readonly=True,
        default=lambda self: self.env.company
    )

    total_entry_encoding = models.MonetaryField('Transactions Subtotal', compute='_end_balance', store=True, help_text="Total of transaction lines.")
    balance_end = models.MonetaryField('Computed Balance', compute='_end_balance', store=True, help_text='Balance as calculated based on Opening Balance and transaction lines')
    difference = models.MonetaryField(compute='_end_balance', store=True, help_text="Difference between the computed ending balance and the specified ending balance.")

    lines = models.OneToManyField('account.bank.statement.line', 'statement', verbose_name='Statement lines', states={'confirm': [('readonly', True)]}, copy=True)
    move_lines = models.OneToManyField('account.move.line', 'statement', verbose_name='Entry lines', states={'confirm': [('readonly', True)]})
    move_line_count = models.IntegerField(compute="_get_move_line_count")

    all_lines_reconciled = models.BooleanField(compute='_check_lines_reconciled')
    user = models.ForeignKey('res.users', verbose_name='Responsible', required=False, default=lambda self: self.env.user)
    cashbox_start = models.ForeignKey('account.bank.statement.cashbox', verbose_name="Starting Cashbox")
    cashbox_end = models.ForeignKey('account.bank.statement.cashbox', verbose_name="Ending Cashbox")
    is_difference_zero = models.BooleanField(compute='_is_difference_zero', verbose_name='Is zero', help_text="Check if difference is zero.")

    class Meta:
        name = 'account.bank.statement'
        verbose_name = _('Bank Statement')
Пример #24
0
class Event(mail.models.Comments):
    name = models.CharField(verbose_name=_('Meeting Subject'), null=True, widget_attrs={'done': [('readonly', True)]})
    status = models.ChoiceField(
        (('draft', _('Unconfirmed')), ('open', _('Confirmed'))), readonly=True, default='draft'
    )

    # is_attendee = models.BooleanField('Attendee', compute='_compute_attendee')
    # attendee_status = models.ChoiceField(Attendee.STATE_SELECTION, verbose_name='Attendee Status', compute='_compute_attendee')
    # display_time = models.CharField('Event Time', compute='_compute_display_time')
    # display_start = models.CharField('Date', compute='_compute_display_start', store=True)
    start = models.DateTimeField(
        verbose_name=_('Start'), null=False,
        help_text="Start date of an event, without time for full days events"
    )
    stop = models.DateTimeField(
        verbose_name=_('Stop'), null=False,
        help_text="Stop date of an event, without time for full days events"
    )

    all_day = models.BooleanField(verbose_name=_('All Day'), states={'done': [('readonly', True)]}, default=False)
    start_date = models.DateField('Start Date', compute='_compute_dates', inverse='_inverse_dates', store=True,
                                  states={'done': [('readonly', True)]}, track_visibility='onchange')
    start_datetime = models.DateTimeField(
        verbose_name=_('Start DateTime'), compute='_compute_dates', inverse='_inverse_dates',
        store=True, states={'done': {'readonly': True}},
        track_visibility='onchange'
    )
    end_date = models.DateField(
        verbose_name=_('End Date'), compute='_compute_dates', inverse='_inverse_dates', store=True,
        states={'done': [('readonly', True)]}, track_visibility='onchange'
    )
    end_datetime = models.DateTimeField(
        verbose_name=_('End Datetime'), compute='_compute_dates', inverse='_inverse_dates', store=True,
        states={'done': [('readonly', True)]},
        track_visibility='onchange'
    )
    duration = models.FloatField(verbose_name=_('Duration'), states={'done': [('readonly', True)]})
    description = models.TextField(verbose_name=_('Description'), states={'done': [('readonly', True)]})
    privacy = models.ChoiceField(
        [('public', 'Everyone'), ('private', 'Only me'), ('confidential', 'Only internal users')],
        verbose_name=_('Privacy'),
        default='public', states={'done': [('readonly', True)]},
    )
    location = models.CharField(
        'Location', states={'done': [('readonly', True)]}, track_visibility='onchange',
        help_text="Location of Event"
    )
    show_as = models.ChoiceField(
        (('free', _('Free')), ('busy', _('Busy'))), verbose_name=_('Show Time as'),
        states={'done': [('readonly', True)]}, default='busy'
    )

    # linked document
    object_id = models.BigIntegerField('Object ID')
    model = models.ForeignKey('ir.model', verbose_name=_('Document Model'), ondelete=models.CASCADE)
    model_name = models.CharField('Document Model Name', related='model.name', readonly=True, store=True)
    activities = models.OneToManyField('mail.activity', 'calendar_event_id', verbose_name='Activities')

    # redifine message_ids to remove autojoin to avoid search to crash in get_recurrent_ids
    # message_ids = models.OneToManyField()

    recurrent_rule = models.CharField(
        verbose_name=_('Recurrent Rule'), compute='_compute_recurrent_rule', inverse='_inverse_recurrent_rule',
        store=True
    )
    recurrent_rule_type = models.ChoiceField(
        (
            ('daily', _('Day(s)')),
            ('weekly', _('Week(s)')),
            ('monthly', _('Month(s)')),
            ('yearly', _('Year(s)')),
        ), verbose_name=_('Recurrence'), states={'done': [('readonly', True)]},
        help_text="Let the event automatically repeat at that interval"
    )
    recurrency = models.BooleanField('Recurrent', help_text="Recurrent Meeting")
    recurrent_id = models.BigIntegerField('Recurrent ID')
    recurrent_id_date = models.DateTimeField('Recurrent ID date')
    end_type = models.ChoiceField(
        (
            ('count', 'Number of repetitions'),
            ('end_date', 'End date')
        ), verbose_name=_('Recurrence Termination'), default='count'
    )
    interval = models.IntegerField(
        verbose_name='Repeat Every', default=1,
        help_text="Repeat every (Days/Week/Month/Year)"
    )
    count = models.IntegerField(verbose_name='Repeat', help_text="Repeat x times", default=1)
    mo = models.BooleanField(verbose_name=_('Mon'))
    tu = models.BooleanField(verbose_name=_('Tue'))
    we = models.BooleanField(verbose_name=_('Wed'))
    th = models.BooleanField(verbose_name=_('Thu'))
    fr = models.BooleanField(verbose_name=_('Fri'))
    sa = models.BooleanField(verbose_name=_('Sat'))
    su = models.BooleanField(verbose_name=_('Sun'))
    month_by = models.ChoiceField([
        ('date', 'Date of month'),
        ('day', 'Day of month')
    ], verbose_name=_('Option'), default='date')
    day = models.IntegerField('Date of month', default=1)
    week_list = models.ChoiceField(
        (
            ('MO', 'Monday'),
            ('TU', 'Tuesday'),
            ('WE', 'Wednesday'),
            ('TH', 'Thursday'),
            ('FR', 'Friday'),
            ('SA', 'Saturday'),
            ('SU', 'Sunday')
        ), verbose_name=_('Weekday')
    )
    by_day = models.ChoiceField(
        (
            ('1', _('First')),
            ('2', _('Second')),
            ('3', _('Third')),
            ('4', _('Fourth')),
            ('5', _('Fifth')),
            ('-1', _('Last')),
        ), verbose_name=_('By day')
    )
    final_date = models.DateField('Repeat Until')
    user_id = models.ForeignKey('res.users', 'Owner', states={'done': [('readonly', True)]},
                                default=lambda self: self.env.user)
    partner_id = models.ForeignKey(
        'res.partner', verbose_name='Responsible', related='user_id.partner_id', readonly=True
    )
    active = models.BooleanField(
        verbose_name=_('Active'), default=True,
        help_text="If the active field is set to false, it will allow you to hide the event alarm information without removing it."
    )
    event_types = models.ManyToManyField('calendar.event.type', verbose_name=_('Tags'))
    attendee = models.OneToManyField(
        'calendar.attendee', 'event', verbose_name=_('Participant'), ondelete=models.CASCADE
    )
    partners = models.OneToManyField(
        'res.partner', 'calendar_event_res_partner_rel', verbose_name='Attendees',
        states={'done': [('readonly', True)]}, default=_default_partners
    )
    alarms = models.ManyToManyField(
        'calendar.alarm', 'calendar_alarm_calendar_event_rel', verbose_name='Reminders',
        ondelete="restrict", copy=False
    )
    is_highlighted = models.BooleanField(compute='_compute_is_highlighted', verbose_name='Is the Event Highlighted')

    class Meta:
        name = 'calendar.event'
        verbose_name = "Event"
Пример #25
0
Файл: ui.py Проект: katrid/orun
class View(models.Model):
    name = models.CharField(max_length=100)
    active = models.BooleanField(label=_('Active'), default=True)
    parent = models.ForeignKey('self')
    view_type = models.ChoiceField((
        ('list', 'List'),
        ('form', 'Form'),
        ('card', 'Card'),
        ('chart', 'Chart'),
        ('calendar', 'Calendar'),
        ('search', 'Search'),
        ('template', 'Template'),
        ('report', 'Report'),
        ('dashboard', 'Dashboard'),
        ('custom', 'Custom'),
        ('class', 'Class'),
    ),
                                   default='form',
                                   null=False)
    mode = models.ChoiceField(
        (('primary', _('Primary')), ('extension', _('Extension'))),
        default='extension',
        null=False)
    model = models.CharField(128, db_index=True)
    priority = models.IntegerField(_('Priority'), default=99, null=False)
    template_name = models.CharField(max_length=256)
    content = models.TextField(caption=_('Content'))
    # ref_id = models.CharField(caption=_('Reference ID'), getter='_get_xml_id')
    # children = models.OneToManyField('self', 'parent')
    class_name = models.CharField(max_length=256,
                                  verbose_name='Python Class Name')

    class Meta:
        name = 'ui.view'
        ordering = ('name', 'priority')

    def save(self, *args, **kwargs):
        if self.parent_id is None:
            self.mode = 'primary'
        if self.view_type is None:
            xml = etree.fromstring(self.render({}))
            self.view_type = xml.tag
        super(View, self).save(*args, **kwargs)

    def _get_xml_id(self):
        obj = apps['ir.object'].objects.get_by_object_id(
            self._meta.name, self.id)
        if obj:
            return obj.name

    def get_content(self, model=None):
        xml = etree.tostring(self.get_xml(model))
        return xml

    def get_xml(self, model, context=None):
        if context is None:
            context = {}
        if model:
            context.update({'opts': model._meta if model else None})
        context['env'] = apps
        return self.compile(context)

    def xpath(self, source, element):
        pos = element.attrib.get('position')
        expr = element.attrib.get('expr')
        target = source
        logger.critical('xpath %s %s' % (expr, self.template_name))
        logger.critical(etree.tostring(element))
        if expr:
            target = target.xpath(expr)[0]
        self._merge(target, pos, element)

    def _merge(self, target: etree.HtmlElement, pos: str,
               element: etree.HtmlElement):
        if pos == 'append':
            for child in element:
                target.append(child)
        elif pos == 'insert':
            for child in reversed(element):
                target.insert(0, etree.fromstring(etree.tostring(child)))
        elif pos == 'before':
            parent = target.getparent()
            idx = parent.index(target)
            for child in reversed(element):
                parent.insert(idx, etree.fromstring(etree.tostring(child)))
        elif pos == 'after':
            parent = target.getparent()
            idx = parent.index(target) + 1
            for child in reversed(element):
                parent.insert(idx, etree.fromstring(etree.tostring(child)))
        elif pos == 'attributes':
            for child in element:
                target.attrib[child.attrib['name']] = child.text
        elif pos == 'replace':
            p = target.getparent()
            idx = p.index(target)
            p.remove(target)
            for child in element:
                p.insert(idx, etree.fromstring(etree.tostring(child)))

    def merge(self, target: etree.HtmlElement, element):
        for child in element:
            if child.tag == 'xpath':
                self.xpath(target, child)
            elif child.tag == 'insert' or child.tag == 'append':
                self._merge(target, child.tag, child)
        for k, v in element.attrib.items():
            target.attrib[k] = v

    def compile(self, context, parent=None):
        view_cls = self.__class__
        children = view_cls.objects.filter(parent_id=self.pk, mode='extension')
        context['ref'] = ref
        context['exec_scalar'] = exec_scalar
        context['exec_query'] = exec_query
        context['query'] = query
        context['models'] = apps
        xml = self._get_content(context)
        xml = etree.fromstring(self._get_content(context))
        if self.parent:
            parent_xml = etree.fromstring(self.parent.render(context))
            self.merge(parent_xml, xml)
            xml = parent_xml

        for child in children:
            self.merge(xml, etree.fromstring(child._get_content(context)))

        self._eval_permissions(xml)
        resolve_refs(xml)
        return xml

    def _eval_permissions(self, xml):
        _groups = {}
        return
        user = self.env.user
        if not user.is_superuser:
            objects = self.env['ir.object']
            children = xml.xpath("//*[@groups]")
            for child in children:
                groups = child.attrib['groups']
                if groups not in _groups:
                    has_groups = len(
                        list(
                            objects.objects.only('id').filter(
                                objects.c.model == 'auth.group',
                                objects.c.name.in_(groups.split(',')),
                                objects.c.object_id.in_(user.groups))[:1])) > 0
                    _groups[groups] = has_groups
                if not _groups[groups]:
                    child.getparent().remove(child)

    def _get_content(self, context):
        if self.view_type == 'report':
            templ = loader.get_template(self.template_name.split(':')[-1])
        else:
            templ = loader.get_template(self.template_name.split(':')[-1])
            # templ = apps.jinja_env.get_or_select_template(self.template_name.split(':')[-1])
            return templ.render(context)
        res = open(templ.template.filename, encoding='utf-8').read()
        return res

    def to_string(self):
        templ = loader.find_template(self.template_name.split(':')[-1])
        with open(templ, encoding='utf-8') as f:
            return f.read()

    def render(self, context):
        from orun.template.loader import get_template
        context['env'] = apps
        context['_'] = gettext
        context['exec_query'] = exec_query
        context['query'] = query
        context['exec_scalar'] = exec_scalar
        context['models'] = apps
        context['ref'] = ref
        if self.view_type in ('dashboard', 'report'):
            context['db'] = {'connection': connection}
        if settings.DEBUG and self.template_name:
            # context['ref'] = g.env.ref
            templ = self.template_name.split(':')[-1]
            if self.view_type in ('dashboard', 'report'):
                content = get_template(self.template_name)
                if isinstance(Template, str):
                    return Template(content).render(context)
                else:
                    return content.render(context)
                return apps.report_env.get_or_select_template(templ).render(
                    **context)
            return loader.get_template(templ).render(context)
        if self.view_type in ('dashboard', 'report') and self.template_name:
            content = get_template(self.template_name)
            return content.render(context)
            # return apps.report_env.from_string(self.content).render(**context)
        if self.view_type == 'dashboard':
            return self.content
        return Template(self.content).render(context)

    @classmethod
    def generate_view(self, request, model, view_type='form'):
        opts = model._meta
        return render_template(request, [
            'views/%s/%s.html' % (opts.name, view_type),
            'views/%s/%s.xml' % (opts.name, view_type),
            'views/%s/%s.xml' % (opts.app_label, view_type),
            'views/%s.xml' % view_type,
        ],
                               context=dict(opts=opts, _=gettext))

    @classmethod
    def render_template(self, request, template, context):
        # find template by ref id
        templ = apps['ir.object'].get_by_natural_key(template).object
        children = list(self.objects.filter(mode='primary', parent=templ.id))
        if children:
            for child in children:
                pass
        else:
            views_env.from_string
Пример #26
0
class WindowAction(Action):
    VIEW_MODE = (
        ('form', 'Form'),
        ('list', 'List'),
        ('card', 'Card'),
        ('search', 'Search'),
        ('calendar', 'Calendar'),
    )
    view = models.ForeignKey('ui.view', label=_('View'))
    domain = models.TextField(label=_('Domain'))
    context = models.TextField(label=_('Context'))
    model = models.CharField(128, null=False, label=_('Model'))
    object_id = models.BigIntegerField(label=_('Object ID'))
    #content_object = GenericForeignKey()
    view_mode = models.CharField(128, default='list,form', label=_('View Mode'))
    target = models.CharField(16, label=_('Target'), choices=(
        ('current', 'Current Window'),
        ('new', 'New Window'),
    ))
    limit = models.IntegerField(default=100, label=_('Limit'))
    auto_search = models.BooleanField(default=True, label=_('Auto Search'))
    # views = models.TextField(getter='_get_views', editable=False, serializable=True)
    view_list = models.OneToManyField('ui.action.window.view')
    view_type = models.SelectionField(VIEW_MODE, default='form')

    class Meta:
        name = 'ui.action.window'
        field_groups = {
            'list_fields': ['name', 'action_type', 'usage', 'view', 'model', 'view_mode', 'limit', 'auto_search']
        }

    def _get_views(self):
        modes = self.view_mode.split(',')
        views = self.view_list.all()
        modes = {mode: None for mode in modes}
        if self.view_id:
            modes[self.view_type] = self.view_id
        for v in views:
            modes[v.view_mode] = v.view_id
        if 'search' not in modes:
            modes['search'] = None
        return modes

    @classmethod
    def from_model(cls, model):
        if isinstance(model, models.Model):
            model = model._meta.name
        return cls.objects.filter(model=model).first()

    def _get_info(self, context):
        info = super()._get_info(context)
        # Send action information as katrid.js protocol
        modes = info['viewModes'] = info.pop('view_mode').split(',')
        # info['viewMode'] = info.pop('view_type')
        info['viewMode'] = modes[0]
        model = apps[self.model]
        info['fields'] = model.admin_get_fields_info()
        info['caption'] = info.pop('name')
        view_id = self.view_id
        views_info = info['viewsInfo'] = {}
        # check if there's a specified view
        if view_id:
            views_info[self.view.view_type] = model._admin_get_view_info(
                view_type=self.view_type, view=view_id, toolbar=True
            )
        views_info.update({
            k: model._admin_get_view_info(view_type=k, view=None, toolbar=True) for k in modes if k not in views_info
        })
        info['viewsInfo']['search'] = model._admin_get_view_info(view_type='search')
        return info
Пример #27
0
class Team(sales_team.models.Team):
    class Meta:
        name = 'crm.team'
        verbose_name = 'Sales Channel'
        verbose_name_plural = 'Sales Channels'

    use_leads = models.BooleanField(
        'Leads',
        help_text=
        "Check this box to filter and qualify incoming requests as leads before converting them into opportunities and assigning them to a salesperson."
    )
    use_opportunities = models.BooleanField(
        'Pipeline',
        help_text=
        "Check this box to manage a presales process with opportunities.")
    alias_id = models.ForeignKey(
        'mail.alias',
        verbose_name='Alias',
        ondelete="restrict",
        required=True,
        help_text=
        "The email address associated with this channel. New emails received will automatically create new leads assigned to the channel."
    )
    unassigned_leads_count = models.IntegerField(
        compute='_compute_unassigned_leads_count',
        verbose_name='Unassigned Leads',
        readonly=True)
    opportunities_count = models.IntegerField(
        compute='_compute_opportunities',
        verbose_name='Number of open opportunities',
        readonly=True)
    opportunities_amount = models.IntegerField(
        compute='_compute_opportunities',
        verbose_name='Opportunities Revenues',
        readonly=True)
    dashboard_graph_model = models.ChoiceField(add_choices=(('crm.lead',
                                                             'Pipeline'), ))
    dashboard_graph_period_pipeline = models.ChoiceField(
        [
            ('week', 'Within a Week'),
            ('month', 'Within a Month'),
            ('year', 'Within a Year'),
        ],
        verbose_name='Expected to Close',
        help_text=
        "The time period this channel's dashboard graph will consider.",
        compute="_compute_dashboard_graph_period_pipeline",
        inverse="_inverse_dashboard_graph_period_pipeline")
    dashboard_graph_group_pipeline = models.ChoiceField(
        [
            ('day', 'Expected Closing Day'),
            ('week', 'Expected Closing Week'),
            ('month', 'Expected Closing Month'),
            ('user', 'Salesperson'),
            ('stage', 'Stage'),
        ],
        verbose_name='Grouping Method',
        default='day',
        help_text="How this channel's dashboard graph will group the results.")

    def _compute_unassigned_leads_count(self):
        leads_data = self.env['crm.lead'].read_group([
            ('team_id', 'in', self.ids),
            ('type', '=', 'lead'),
            ('user_id', '=', False),
        ], ['team_id'], ['team_id'])
        counts = {
            datum['team_id'][0]: datum['team_id_count']
            for datum in leads_data
        }
        for team in self:
            team.unassigned_leads_count = counts.get(team.id, 0)

    def _compute_opportunities(self):
        opportunity_data = self.env['crm.lead'].objects.filter([
            ('team_id', 'in', self.ids),
            ('probability', '<', 100),
            ('type', '=', 'opportunity'),
        ]).read(['planned_revenue', 'probability', 'team_id'])
        counts = {}
        amounts = {}
        for datum in opportunity_data:
            counts.setdefault(datum['team_id'][0], 0)
            amounts.setdefault(datum['team_id'][0], 0)
            counts[datum['team_id'][0]] += 1
            amounts[datum['team_id'][0]] += (datum.get('planned_revenue', 0) *
                                             datum.get('probability', 0) /
                                             100.0)
        for team in self:
            team.opportunities_count = counts.get(team.id, 0)
            team.opportunities_amount = amounts.get(team.id, 0)

    def _compute_dashboard_graph_period_pipeline(self):
        for channel in self:
            channel.dashboard_graph_period_pipeline = channel.dashboard_graph_period

    def _inverse_dashboard_graph_period_pipeline(self):
        for channel in self.filtered(
                lambda ch: ch.dashboard_graph_model == 'crm.lead'):
            channel.dashboard_graph_period = channel.dashboard_graph_period_pipeline

    def get_alias_model_name(self, vals):
        return 'crm.lead'

    def get_alias_values(self):
        has_group_use_lead = self.env.user.has_group('crm.group_use_lead')
        values = super(Team, self).get_alias_values()
        values['alias_defaults'] = defaults = safe_eval(self.alias_defaults
                                                        or "{}")
        defaults[
            'type'] = 'lead' if has_group_use_lead and self.use_leads else 'opportunity'
        defaults['team_id'] = self.id
        return values

    @api.onchange('use_leads', 'use_opportunities')
    def _onchange_use_leads_opportunities(self):
        if not self.use_leads and not self.use_opportunities:
            self.alias_name = False
        if not self.use_opportunities and self.use_leads:
            self.use_leads = False

    @api.onchange('team_type')
    def _onchange_team_type(self):
        if self.team_type == 'sales':
            self.use_opportunities = True
            self.use_leads = lambda self: self.user_has_groups(
                'crm.group_use_lead')
            self.dashboard_graph_model = 'crm.lead'
        else:
            self.use_opportunities = False
            self.use_leads = False
        return super(Team, self)._onchange_team_type()

    @api.onchange('dashboard_graph_model')
    def _onchange_dashboard_graph_model(self):
        if self.dashboard_graph_model == 'crm.lead':
            self.dashboard_graph_period_pipeline = self.dashboard_graph_period
            self.dashboard_graph_group_pipeline = self.dashboard_graph_group
        else:
            self.dashboard_graph_period = self.dashboard_graph_period_pipeline
            if not self.dashboard_graph_group:
                self.dashboard_graph_group = self._fields[
                    'dashboard_graph_group'].default(self)

    @api.onchange('dashboard_graph_group_pipeline')
    def _onchange_dashboard_graph_group_pipeline(self):
        if self.dashboard_graph_group_pipeline == 'stage':
            self.dashboard_graph_group = False
        else:
            self.dashboard_graph_group = self.dashboard_graph_group_pipeline

    @api.constrains('dashboard_graph_model', 'use_opportunities')
    def _check_graph_model(self):
        if not self.use_opportunities and self.dashboard_graph_model == 'crm.lead':
            raise ValidationError(
                _("You have to enable the Pipeline on your Sales Team to be able to set it as a content for the graph"
                  ))

    @api.multi
    def write(self, vals):
        result = super(Team, self).write(vals)
        if 'use_leads' in vals or 'alias_defaults' in vals:
            for team in self:
                team.alias_id.write(team.get_alias_values())
        return result

    #TODO JEM : refactor this stuff with xml action, proper customization,
    @api.model
    def action_your_pipeline(self):
        action = self.env.ref('crm.crm_lead_opportunities_tree_view').read()[0]
        user_team_id = self.env.user.sale_team_id.id
        if not user_team_id:
            user_team_id = self.search([], limit=1).id
            action['help'] = _(
                """<p class='o_view_nocontent_smiling_face'>Add new opportunities</p><p>
    Looks like you are not a member of a Sales Team. You should add yourself
    as a member of one of the Sales Team.
</p>""")
            if user_team_id:
                action[
                    'help'] += "<p>As you don't belong to any Sales Team, Odoo opens the first one by default.</p>"

        action_context = safe_eval(action['context'], {'uid': self.env.uid})
        if user_team_id:
            action_context['default_team_id'] = user_team_id

        action['context'] = action_context
        return action

    def _compute_dashboard_button_name(self):
        opportunity_teams = self.filtered('use_opportunities')
        opportunity_teams.update(
            {'dashboard_button_name': gettext("Pipeline")})
        super(Team, self - opportunity_teams)._compute_dashboard_button_name()

    def action_primary_channel_button(self):
        if self.use_opportunities:
            action = self.env.ref(
                'crm.crm_case_form_view_salesteams_opportunity').read()[0]
            return action
        return super(Team, self).action_primary_channel_button()

    def _graph_get_dates(self, today):
        """ return a coherent start and end date for the dashboard graph according to the graph settings.
        """
        if self.dashboard_graph_model == 'crm.lead':
            if self.dashboard_graph_group == 'month':
                start_date = today.replace(day=1)
            elif self.dashboard_graph_group == 'week':
                start_date = today - relativedelta(
                    days=today.isocalendar()[2] - 1)
            else:
                start_date = today

            if self.dashboard_graph_period == 'week':
                end_date = today + relativedelta(weeks=1)
            elif self.dashboard_graph_period == 'year':
                end_date = today + relativedelta(years=1)
            else:
                end_date = today + relativedelta(months=1)

            # we take the end of the preceding month/week/day if we group by month/week/day
            # (to avoid having twice the same month/week/day from different years/month/week)
            if self.dashboard_graph_group == 'month':
                end_date = end_date.replace(day=1) - relativedelta(days=1)
            elif self.dashboard_graph_group == 'week':
                end_date -= relativedelta(days=end_date.isocalendar()[2])
            else:
                end_date -= relativedelta(days=1)

            return [start_date, end_date]
        return super(Team, self)._graph_get_dates(today)

    def _get_graph(self):
        graph_datas = super(Team, self)._get_graph()
        if self.dashboard_graph_model == 'crm.lead' and self.dashboard_graph_group_pipeline == 'stage':
            stage_ids = [
                d['label'] for d in graph_datas[0]['values']
                if d['label'] is not None
            ]
            stage_data = self.env['crm.stage'].browse(stage_ids).read(
                ['sequence', 'name'])
            stage_data = {
                d['id']: {
                    'name': d['name'],
                    'sequence': d['sequence']
                }
                for d in stage_data
            }
            # use "Undefined" stage for unset stage records
            stage_data[None] = {'name': _('Undefined'), 'sequence': -1}
            graph_datas[0]['values'] = sorted(
                graph_datas[0]['values'],
                key=lambda el: stage_data[el['label']]['sequence'])
            for gdata in graph_datas[0]['values']:
                gdata['label'] = stage_data[gdata['label']]['name']
        return graph_datas

    def _graph_date_column(self):
        if self.dashboard_graph_model == 'crm.lead':
            return 'date_deadline'
        return super(Team, self)._graph_date_column()

    def _graph_x_query(self):
        if self.dashboard_graph_model == 'crm.lead' and self.dashboard_graph_group_pipeline == 'stage':
            return 'stage_id'
        return super(Team, self)._graph_x_query()

    def _graph_y_query(self):
        if self.dashboard_graph_model == 'crm.lead':
            return 'SUM(expected_revenue)'
        return super(Team, self)._graph_y_query()

    def _graph_title_and_key(self):
        if self.dashboard_graph_model == 'crm.lead':
            return ['', _('Pipeline: Expected Revenue')]  # no more title
        return super(Team, self)._graph_title_and_key()
Пример #28
0
class Query(models.Model):
    name = models.CharField(label=_('Name'), localize=True)
    category = models.ForeignKey(Category)
    sql = models.TextField()
    context = models.TextField()
    params = models.TextField()
    public = models.BooleanField(
        default=False,
        label='Public/External access',
        help_text='Has public external/anonymous access')
    published = models.BooleanField(default=True)

    class Meta:
        name = 'ir.query'

    def get_by_natural_key(self, category, name):
        return self.objects.filter({'category': category, 'name': name}).one()

    def _apply_param(self, param, values):
        sql = []
        for k, v in param.items():
            if k == 'OR':
                return ' OR '.join([self._apply_param(p, values) for p in v])
            cond = k.split('__')
            field = cond[0]
            if len(cond) > 1:
                for lookup in cond[1:]:
                    # name = 'param_%s' % (len(values) + 1)
                    if lookup == 'icontains':
                        s = f'"{field}" like ?'
                        v = f'%{v}%'
                    else:
                        s = f'"{field}" = ?'
                    values.append(v)
                    sql.append('(%s)' % s)
            else:
                # name = 'param_%s' % (len(values.values()) + 1)
                values.append(v)
                s = f'"{field}" = ?'
                sql.append('(%s)' % s)
        return '(%s)' % ' OR '.join(sql)

    def _apply_search(self, sql, params, values):
        if params:
            where = []
            for param in params:
                where.append(self._apply_param(param, values))
            where = ' AND '.join(where)
            sql = """SELECT * FROM (%s) as q1 WHERE %s""" % (sql, where)
        return sql

    def _prepare_context(self, request):
        ctx = {
            'request': request,
            'user_id': self.env.user_id,
            'user': self.env.user,
        }
        # evaluate query params
        return eval(self.context, ctx)

    @api.classmethod
    def read(cls,
             id,
             with_description=False,
             as_dict=False,
             fields=None,
             **kwargs):
        q = cls.objects.get(pk=id)
        params = q.context
        if params:
            params = q._prepare_context()
        else:
            params = {}

        if 'filter' in kwargs:
            params.update(kwargs['filter'])
        sql = Template(q.sql).render(**params)
        values = []
        if 'params' in kwargs:
            # apply query search params
            sql = q._apply_search(sql, kwargs['params'], values)
        if (fields):
            sql = 'SELECT top 100 %s FROM (%s) as __q' % (', '.join(fields))

        cur = connection.cursor()
        cur.execute(sql, values)
        desc = cur.cursor.description
        datatype_map = {
            datetime.date: 'DateField',
            datetime.datetime: 'DateTimeField',
            str: 'CharField',
            Decimal: 'DecimalField',
            float: 'FloatField',
            int: 'IntegerField',
        }
        if with_description:
            fields = [{
                'name': f[0],
                'type': datatype_map.get(f[1], 'CharField'),
                'size': f[2]
            } for f in desc]
        else:
            fields = [f[0] for f in desc]

        if as_dict:
            return {
                'fields':
                fields,
                'data': [{
                    fields[i]: float(col) if isinstance(col, Decimal) else col
                    for i, col in enumerate(row)
                } for row in cur.fetchall()],
            }
        else:
            return {
                'fields':
                fields,
                'data': [[
                    float(col) if isinstance(col, Decimal) else col
                    for col in row
                ] for row in cur.fetchall()],
            }

    @api.classmethod
    def list_all(cls):
        return {
            'data': [{
                'id': q.pk,
                'category': str(q.category),
                'name': q.name,
                'params': q.params,
            } for q in cls.objects.all()]
        }

    @api.classmethod
    def clone(cls, id, data):
        old_query = cls.objects.get(pk=id)
        new_query = cls.objects.create()
        new_query.parent = old_query
        new_query.sql = old_query.sql
        new_query.category = old_query.category
Пример #29
0
class Meeting(calendar.models.Meeting):
    opportunity_id = models.ForeignKey('crm.lead', verbose_name=_('Opportunity'), domain={'type': 'opportunity'})
Пример #30
0
class ReportAction(Action):
    report_type = models.CharField(32,
                                   null=False,
                                   verbose_name=_('Report Type'))
    model = models.CharField(128)
    view = models.ForeignKey('ui.view')

    class Meta:
        name = 'ui.action.report'

    def to_dict(self, *args, **kwargs):
        from lxml import etree
        data = super(ReportAction, self).to_dict(*args, **kwargs)
        model = None
        if self.model:
            model = apps[self.model]

        rep_type = None
        if self.view and self.view.template_name:
            rep_type = self.view.template_name.rsplit('.', 1)[1]
            engine = get_engine(REPORT_ENGINES[rep_type])
            if rep_type == 'jinja2':
                templ = loader.get_template(self.view.template_name)
                params = templ.blocks.get('params')
                if params:
                    ctx = templ.new_context({})
                    doc = ''.join(params(ctx))
                    if not model:
                        xml = etree.fromstring(doc)
                        model_name = xml.attrib.get('model')
                        if model_name:
                            model = apps[model_name]
                            data['fields'] = model.get_fields_info(xml)
                    data['content'] = doc
            elif rep_type == 'pug':
                templ = loader.find_template(self.view.template_name)
                with open(templ, 'r', encoding='utf-8') as f:
                    params = engine.extract_params(f.read())
                if params is not None:
                    print(params.tostring())
                    data['content'] = params.tostring()
            else:
                if rep_type == 'xml':
                    templ = loader.find_template(self.view.template_name)
                    with open(templ, 'r', encoding='utf-8') as f:
                        xml = f.read()
                else:
                    xml = self.view._get_content({})
                if isinstance(xml, str):
                    xml = etree.fromstring(xml)
                # xml = self.view.get_xml(model)
                if model:
                    data['fields'] = model.get_fields_info(xml=xml)
                params = xml.find('params')
                if params is not None:
                    if xml.tag == 'report' and 'model' in xml.attrib:
                        params.attrib['model'] = xml.attrib['model']
                        if not model:
                            model = apps[xml.attrib['model']]
                            data['fields'] = model.get_fields_info(params)

                        # model = app[model]
                        # for field in params:
                        #     if field.tag == 'field' and 'name' in field.attrib:
                        #         fld = model._meta.fields[field.attrib['name']]
                    xml = params
                    data['content'] = etree.tostring(
                        xml, encoding='utf-8').decode('utf-8')
        if 'content' not in data:
            data['content'] = '<params/>'
        return data

    def _export_report(self, format='pdf', params=None, where=None):
        qs = model = None
        if self.model:
            model = apps[self.model]
            qs = model.objects.all()
        _params = defaultdict(list)

        rep_type = None
        if self.view and self.view.template_name:
            rep_type = self.view.template_name.rsplit('.', 1)[1]

        if rep_type == 'pug':
            xml = self.view.to_string()
        elif rep_type == 'rep':
            xml = self.view.get_xml(model)
            report_file = xml.attrib['file']
            with open(
                    loader.get_template(report_file).template.filename,
                    'rb') as f:
                xml = f.read()
        else:
            xml = self.view.get_xml(model)
            report_file = xml.attrib['file']
            if rep_type == 'xml':
                with open(
                        loader.get_template(report_file).template.filename,
                        'rb') as f:
                    xml = f.read()
            rep_type = report_file.rsplit('.', 1)[1]

        engine = get_engine(REPORT_ENGINES[rep_type])
        fname = uuid.uuid4().hex + '.pdf'
        output_path = os.path.join(settings.REPORT_PATH, fname)
        rep = engine.export(
            xml,
            connection=ConnectionProxy(connection),
            # company=g.user.user_company,
            name=self.name,
            template='admin/reports/base.jinja2',
            company=apps['auth.user'].objects.get(pk=1).user_company,
            format=format,
            model=model,
            query=qs,
            report_title=self.name,
            params=params,
            where=where,
            output_file=output_path,
        )
        if not isinstance(rep, (dict, str)):
            return rep
        if rep:
            if not isinstance(rep, str):
                rep = rep.export(format=format)
            out_file = '/web/reports/' + os.path.basename(rep)
            print('outfile', out_file)
            return {
                'open': out_file,
                'name': self.name,
            }

    @api.classmethod
    def auto_report(cls, model, params=None, title=None):
        model_class = apps[model]
        qs = model_class.objects.all()
        default_view = model_class._admin_select_template('auto_report')
        templ = default_view.render(context={'opts': model_class._meta})
        engine = get_engine(REPORT_ENGINES['pug'])
        fname = uuid.uuid4().hex + '.pdf'
        output_path = os.path.join(settings.REPORT_PATH, fname)
        rep = engine.export(
            templ,
            connection=ConnectionProxy(connection),
            # company=g.user.user_company,
            name=title or model,
            template='admin/reports/base.jinja2',
            company=apps['auth.user'].objects.get(pk=1).user_company,
            format=format,
            model=model_class,
            queryset=qs,
            report_title=title or model_class._meta.verbose_name_plural,
            params=params,
            where=None,
            output_file=output_path,
        )
        if not isinstance(rep, (dict, str)):
            return rep
        if rep:
            out_file = '/web/reports/' + os.path.basename(rep)
            return {
                'open': out_file,
                'name': model_class._meta.verbose_name_plural,
            }

    @api.classmethod
    def export_report(cls, id, format='pdf', params=None, where=None):
        # TODO check permission
        if isinstance(id, list):
            id = id[0]
        if isinstance(id, models.Model):
            rep = id
        else:
            rep = cls.objects.get(pk=id)
        if params:
            where = params.pop('where', None)
        return rep._export_report(format=format, params=params, where=where)

    @api.classmethod
    def on_execute_action(cls, action_id, context):
        fmt = context.pop('format', 'pdf')
        params = context.pop('params', None)
        if params is None:
            if 'active_id' in context:
                params = {
                    'where': {
                        'pk': context['active_id']
                    },
                }
        return cls.export_report(action_id, fmt, params)