示例#1
0
class IfrsLines(models.Model):

    _name = 'ifrs.lines'
    _order = 'ifrs_id, sequence'

    def _get_ifrs_query(self, cr, uid, brw, context=None):
        """ Fetches a semi-query to be provided as context into aml"""
        context = dict(context or {})
        query = ''
        if not brw.filter_id:
            return query
        args = eval(brw.filter_id.domain)
        query = self.pool['account.move.line']._where_calc(cr,
                                                           uid,
                                                           args,
                                                           context=context)
        where_clause, where_clause_params = query.get_sql()[1:]
        where_clause = where_clause.replace('account_move_line', 'l')
        query = cr.mogrify(where_clause, where_clause_params)
        return query

    def _get_sum_total(self,
                       cr,
                       uid,
                       brw,
                       operand,
                       number_month=None,
                       one_per=False,
                       bag=None,
                       context=None):
        """ Calculates the sum of the line total_ids & operand_ids the current
        ifrs.line
        @param number_month: period to compute
        """
        context = context and dict(context) or {}
        res = 0

        # If the report is two or twelve columns, will choose the field needed
        # to make the sum
        if context.get('whole_fy', False) or one_per:
            field_name = 'ytd'
        else:
            field_name = 'period_%s' % str(number_month)

        # It takes the sum of the total_ids & operand_ids
        for ttt in getattr(brw, operand):
            res += bag[ttt.id].get(field_name, 0.0)
        return res

    def _get_sum_detail(self,
                        cr,
                        uid,
                        ids=None,
                        number_month=None,
                        context=None):
        """ Calculates the amount sum of the line type == 'detail'
        @param number_month: periodo a calcular
        """
        fy_obj = self.pool.get('account.fiscalyear')
        period_obj = self.pool.get('account.period')
        context = context and dict(context) or {}
        cx = context.copy()
        res = 0.0

        if not cx.get('fiscalyear'):
            cx['fiscalyear'] = fy_obj.find(cr, uid)

        fy_id = cx['fiscalyear']

        brw = self.browse(cr, uid, ids)

        if brw.acc_val == 'init':
            if cx.get('whole_fy', False):
                cx['periods'] = period_obj.search(
                    cr, uid, [('fiscalyear_id', '=', fy_id),
                              ('special', '=', True)])
            else:
                period_from = period_obj.search(cr, uid,
                                                [('fiscalyear_id', '=', fy_id),
                                                 ('special', '=', True)])
                # Case when the period_from is the first non-special period
                # of the fiscalyear
                if period_obj.browse(cr, uid, cx['period_from']).date_start ==\
                        fy_obj.browse(cr, uid, fy_id).date_start:
                    cx['period_to'] = period_from[0]
                else:
                    cx['period_to'] = period_obj.previous(
                        cr, uid, cx['period_from'])
                cx['period_from'] = period_from[0]
        elif brw.acc_val == 'var':
            # it is going to be the one sent by the previous cx
            if cx.get('whole_fy', False):
                cx['periods'] = period_obj.search(
                    cr, uid, [('fiscalyear_id', '=', fy_id),
                              ('special', '=', False)])
        else:
            # it is going to be from the fiscalyear's beginning
            if cx.get('whole_fy', False):
                cx['periods'] = period_obj.search(
                    cr, uid, [('fiscalyear_id', '=', fy_id)])
            else:
                period_from = period_obj.search(cr, uid,
                                                [('fiscalyear_id', '=', fy_id),
                                                 ('special', '=', True)])
                cx['period_from'] = period_from[0]
                cx['periods'] = \
                    period_obj.build_ctx_periods(cr, uid, cx['period_from'],
                                                 cx['period_to'])

        if brw.type == 'detail':
            # Si es de tipo detail
            # If we have to only take into account a set of Journals
            cx['journal_ids'] = [aj_brw.id for aj_brw in brw.journal_ids]
            cx['analytic'] = [an.id for an in brw.analytic_ids]
            cx['ifrs_tax'] = [tx.id for tx in brw.tax_code_ids]
            cx['ifrs_partner'] = [p_brw.id for p_brw in brw.partner_ids]
            cx['ifrs_query'] = self._get_ifrs_query(cr, uid, brw, context)

            # NOTE: This feature is not yet been implemented
            # cx['partner_detail'] = cx.get('partner_detail')

            # Refreshing record with new context
            brw = self.browse(cr, uid, ids, context=cx)

            for aa in brw.cons_ids:
                # Se hace la sumatoria de la columna balance, credito o debito.
                # Dependiendo de lo que se escoja en el wizard
                if brw.value == 'debit':
                    res += aa.debit
                elif brw.value == 'credit':
                    res += aa.credit
                else:
                    res += aa.balance
        return res

    def _get_logical_operation(self, cr, uid, brw, ilf, irg, context=None):
        def result(brw, ifn, ilf, irg):
            if getattr(brw, ifn) == 'subtract':
                res = ilf - irg
            elif getattr(brw, ifn) == 'addition':
                res = ilf + irg
            elif getattr(brw, ifn) == 'lf':
                res = ilf
            elif getattr(brw, ifn) == 'rg':
                res = irg
            elif getattr(brw, ifn) == 'zr':
                res = 0.0
            return res

        context = dict(context or {})
        fnc = getattr(op, brw.logical_operation)

        if fnc(ilf, irg):
            res = result(brw, 'logical_true', ilf, irg)
        else:
            res = result(brw, 'logical_false', ilf, irg)
        return res

    def _get_grand_total(self,
                         cr,
                         uid,
                         ids,
                         number_month=None,
                         one_per=False,
                         bag=None,
                         context=None):
        """ Calculates the amount sum of the line type == 'total'
        @param number_month: periodo a calcular
        """
        fy_obj = self.pool.get('account.fiscalyear')
        context = context and dict(context) or {}
        cx = context.copy()
        res = 0.0

        if not cx.get('fiscalyear'):
            cx['fiscalyear'] = fy_obj.find(cr, uid)

        brw = self.browse(cr, uid, ids)
        res = self._get_sum_total(cr,
                                  uid,
                                  brw,
                                  'total_ids',
                                  number_month,
                                  one_per=one_per,
                                  bag=bag,
                                  context=cx)

        if brw.operator in ('subtract', 'condition', 'percent', 'ratio',
                            'product'):
            so = self._get_sum_total(cr,
                                     uid,
                                     brw,
                                     'operand_ids',
                                     number_month,
                                     one_per=one_per,
                                     bag=bag,
                                     context=cx)
            if brw.operator == 'subtract':
                res -= so
            elif brw.operator == 'condition':
                res = self._get_logical_operation(cr,
                                                  uid,
                                                  brw,
                                                  res,
                                                  so,
                                                  context=cx)
            elif brw.operator == 'percent':
                res = so != 0 and (100 * res / so) or 0.0
            elif brw.operator == 'ratio':
                res = so != 0 and (res / so) or 0.0
            elif brw.operator == 'product':
                res = res * so
        return res

    def _get_constant(self,
                      cr,
                      uid,
                      ids=None,
                      number_month=None,
                      context=None):
        """ Calculates the amount sum of the line of constant
        @param number_month: periodo a calcular
        """
        cx = context or {}
        brw = self.browse(cr, uid, ids, context=cx)
        if brw.constant_type == 'constant':
            return brw.constant
        fy_obj = self.pool.get('account.fiscalyear')
        period_obj = self.pool.get('account.period')

        if not cx.get('fiscalyear'):
            cx['fiscalyear'] = fy_obj.find(cr, uid, dt=None, context=cx)

        if not cx.get('period_from', False) and not cx.get('period_to', False):
            if context.get('whole_fy', False):
                cx['period_from'] = period_obj.find_special_period(
                    cr, uid, cx['fiscalyear'])
            cx['period_to'] = period_obj.search(
                cr, uid, [('fiscalyear_id', '=', cx['fiscalyear'])])[-1]

        if brw.constant_type == 'period_days':
            res = period_obj._get_period_days(cr, uid, cx['period_from'],
                                              cx['period_to'])
        elif brw.constant_type == 'fy_periods':
            res = fy_obj._get_fy_periods(cr, uid, cx['fiscalyear'])
        elif brw.constant_type == 'fy_month':
            res = fy_obj._get_fy_month(cr, uid, cx['fiscalyear'],
                                       cx['period_to'])
        elif brw.constant_type == 'number_customer':
            res = self._get_number_customer_portfolio(cr, uid, ids,
                                                      cx['fiscalyear'],
                                                      cx['period_to'], cx)
        return res

    def exchange(self,
                 cr,
                 uid,
                 ids,
                 from_amount,
                 to_currency_id,
                 from_currency_id,
                 exchange_date,
                 context=None):
        context = context and dict(context) or {}
        if from_currency_id == to_currency_id:
            return from_amount
        curr_obj = self.pool.get('res.currency')
        context['date'] = exchange_date
        return curr_obj.compute(cr,
                                uid,
                                from_currency_id,
                                to_currency_id,
                                from_amount,
                                context=context)

    def _get_amount_value(self,
                          cr,
                          uid,
                          ids,
                          ifrs_line=None,
                          period_info=None,
                          fiscalyear=None,
                          exchange_date=None,
                          currency_wizard=None,
                          number_month=None,
                          target_move=None,
                          pdx=None,
                          undefined=None,
                          two=None,
                          one_per=False,
                          bag=None,
                          context=None):
        """ Returns the amount corresponding to the period of fiscal year
        @param ifrs_line: linea a calcular monto
        @param period_info: informacion de los periodos del fiscal year
        @param fiscalyear: selected fiscal year
        @param exchange_date: date of change currency
        @param currency_wizard: currency in the report
        @param number_month: period number
        @param target_move: target move to consider
        """

        context = context and dict(context) or {}
        # TODO: Current Company's Currency shall be used: the one on wizard
        from_currency_id = ifrs_line.ifrs_id.company_id.currency_id.id
        to_currency_id = currency_wizard

        if number_month:
            if two:
                context = {
                    'period_from': number_month,
                    'period_to': number_month
                }
            else:
                period_id = period_info[number_month][1]
                context = {'period_from': period_id, 'period_to': period_id}
        else:
            context = {'whole_fy': True}

        # NOTE: This feature is not yet been implemented
        # context['partner_detail'] = pdx
        context['fiscalyear'] = fiscalyear
        context['state'] = target_move

        if ifrs_line.type == 'detail':
            res = self._get_sum_detail(cr,
                                       uid,
                                       ifrs_line.id,
                                       number_month,
                                       context=context)
        elif ifrs_line.type == 'total':
            res = self._get_grand_total(cr,
                                        uid,
                                        ifrs_line.id,
                                        number_month,
                                        one_per=one_per,
                                        bag=bag,
                                        context=context)
        elif ifrs_line.type == 'constant':
            res = self._get_constant(cr,
                                     uid,
                                     ifrs_line.id,
                                     number_month,
                                     context=context)
        else:
            res = 0.0

        if ifrs_line.type == 'detail':
            res = self.exchange(cr,
                                uid,
                                ids,
                                res,
                                to_currency_id,
                                from_currency_id,
                                exchange_date,
                                context=context)
        return res

    def _get_dict_amount_with_operands(self,
                                       cr,
                                       uid,
                                       ids,
                                       ifrs_line,
                                       period_info=None,
                                       fiscalyear=None,
                                       exchange_date=None,
                                       currency_wizard=None,
                                       month_number=None,
                                       target_move=None,
                                       pdx=None,
                                       undefined=None,
                                       two=None,
                                       one_per=False,
                                       bag=None,
                                       context=None):
        """ Integrate operand_ids field in the calculation of the amounts for
        each line
        @param ifrs_line: linea a calcular monto
        @param period_info: informacion de los periodos del fiscal year
        @param fiscalyear: selected fiscal year
        @param exchange_date: date of change currency
        @param currency_wizard: currency in the report
        @param month_number: period number
        @param target_move: target move to consider
        """

        context = dict(context or {})

        direction = ifrs_line.inv_sign and -1.0 or 1.0

        res = {}
        for number_month in range(1, 13):
            field_name = 'period_%(month)s' % dict(month=number_month)
            bag[ifrs_line.id][field_name] = self._get_amount_value(
                cr,
                uid,
                ids,
                ifrs_line,
                period_info,
                fiscalyear,
                exchange_date,
                currency_wizard,
                number_month,
                target_move,
                pdx,
                undefined,
                two,
                one_per=one_per,
                bag=bag,
                context=context) * direction
            res[number_month] = bag[ifrs_line.id][field_name]

        return res

    def _get_amount_with_operands(self,
                                  cr,
                                  uid,
                                  ids,
                                  ifrs_l,
                                  period_info=None,
                                  fiscalyear=None,
                                  exchange_date=None,
                                  currency_wizard=None,
                                  number_month=None,
                                  target_move=None,
                                  pdx=None,
                                  undefined=None,
                                  two=None,
                                  one_per=False,
                                  bag=None,
                                  context=None):
        """ Integrate operand_ids field in the calculation of the amounts for
        each line
        @param ifrs_line: linea a calcular monto
        @param period_info: informacion de los periodos del fiscal year
        @param fiscalyear: selected fiscal year
        @param exchange_date: date of change currency
        @param currency_wizard: currency in the report
        @param number_month: period number
        @param target_move: target move to consider
        """

        context = context and dict(context) or {}

        if not number_month:
            context = {'whole_fy': True}

        res = self._get_amount_value(cr,
                                     uid,
                                     ids,
                                     ifrs_l,
                                     period_info,
                                     fiscalyear,
                                     exchange_date,
                                     currency_wizard,
                                     number_month,
                                     target_move,
                                     pdx,
                                     undefined,
                                     two,
                                     one_per=one_per,
                                     bag=bag,
                                     context=context)

        res = ifrs_l.inv_sign and (-1.0 * res) or res
        bag[ifrs_l.id]['ytd'] = res

        return res

    def _get_number_customer_portfolio(self,
                                       cr,
                                       uid,
                                       ids,
                                       fyr,
                                       period,
                                       context=None):
        ifrs_brw = self.browse(cr, uid, ids, context=context)
        company_id = ifrs_brw.ifrs_id.company_id.id
        if context.get('whole_fy', False):
            period_fy = [('period_id.fiscalyear_id', '=', fyr),
                         ('period_id.special', '=', False)]
        else:
            period_fy = [('period_id', '=', period)]
        invoice_obj = self.pool.get('account.invoice')
        invoice_ids = invoice_obj.search(
            cr, uid, [('type', '=', 'out_invoice'),
                      ('state', 'in', (
                          'open',
                          'paid',
                      )), ('company_id', '=', company_id)] + period_fy)
        partner_number = \
            set([inv.partner_id.id for inv in
                 invoice_obj.browse(cr, uid, invoice_ids, context=context)])
        return len(list(partner_number))

    def onchange_sequence(self, cr, uid, ids, sequence, context=None):
        context = context and dict(context) or {}
        return {'value': {'priority': sequence}}

    @api.returns('self')
    def _get_default_help_bool(self):
        ctx = dict(self._context)
        return ctx.get('ifrs_help', True)

    @api.returns('self')
    def _get_default_sequence(self):
        ctx = dict(self._context)
        res = 0
        if not ctx.get('ifrs_id'):
            return res + 10
        ifrs_lines_ids = self.search([('ifrs_id', '=', ctx['ifrs_id'])])
        if ifrs_lines_ids:
            res = max(line.sequence for line in ifrs_lines_ids)
        return res + 10

    def onchange_type_without(self,
                              cr,
                              uid,
                              ids,
                              ttype,
                              operator,
                              context=None):
        context = context and dict(context) or {}
        res = {}
        if ttype == 'total' and operator == 'without':
            res = {'value': {'operand_ids': []}}
        return res

    def write(self, cr, uid, ids, vals, context=None):
        ids = isinstance(ids, (int, long)) and [ids] or ids
        res = super(IfrsLines, self).write(cr, uid, ids, vals)
        for ifrs_line in self.pool.get('ifrs.lines').browse(cr, uid, ids):
            if ifrs_line.type == 'total' and ifrs_line.operator == 'without':
                vals['operand_ids'] = [(6, 0, [])]
                super(IfrsLines, self).write(cr, uid, ifrs_line.id, vals)
        return res

    help = fields.Boolean(string='Show Help',
                          copy=False,
                          related='ifrs_id.help',
                          default=_get_default_help_bool,
                          help='Allows you to show the help in the form')
    # Really!!! A repeated field with same functionality! This was done due
    # to the fact that web view everytime that sees sequence tries to allow
    # you to change the values and this feature here is undesirable.
    sequence = fields.Integer(
        string='Sequence',
        default=_get_default_sequence,
        help=('Indicates the order of the line in the report. The sequence '
              'must be unique and unrepeatable'))
    priority = fields.Integer(
        string='Sequence',
        default=_get_default_sequence,
        related='sequence',
        help=('Indicates the order of the line in the report. The sequence '
              'must be unique and unrepeatable'))
    name = fields.Char(
        string='Name',
        size=128,
        required=True,
        translate=True,
        help=('Line name in the report. This name can be translatable, if '
              'there are multiple languages loaded it can be translated'))
    type = fields.Selection(
        [('abstract', 'Abstract'), ('detail', 'Detail'),
         ('constant', 'Constant'), ('total', 'Total')],
        string='Type',
        required=True,
        default='abstract',
        help=('Line type of report:  \n-Abstract(A),\n-Detail(D), '
              '\n-Constant(C),\n-Total(T)'))
    constant = fields.Float(
        string='Constant',
        help=('Fill this field with your own constant that will be used '
              'to compute in your other lines'),
        readonly=False)
    constant_type = fields.Selection(
        [('constant', 'My Own Constant'), ('period_days', 'Days of Period'),
         ('fy_periods', "FY's Periods"), ('fy_month', "FY's Month"),
         ('number_customer', "Number of customers* in portfolio")],
        string='Constant Type',
        required=False,
        help='Constant Type')
    ifrs_id = fields.Many2one('ifrs.ifrs', string='IFRS', required=True)
    company_id = fields.Many2one('res.company',
                                 string='Company',
                                 related='ifrs_id.company_id',
                                 store=True)
    amount = fields.Float(
        string='Amount',
        readonly=True,
        help=('This field will update when you click the compute button in '
              'the IFRS doc form'))
    cons_ids = fields.Many2many('account.account',
                                'ifrs_account_rel',
                                'ifrs_lines_id',
                                'account_id',
                                string='Consolidated Accounts')
    journal_ids = fields.Many2many('account.journal',
                                   'ifrs_journal_rel',
                                   'ifrs_lines_id',
                                   'journal_id',
                                   string='Journals',
                                   required=False)
    analytic_ids = fields.Many2many('account.analytic.account',
                                    'ifrs_analytic_rel',
                                    'ifrs_lines_id',
                                    'analytic_id',
                                    string='Consolidated Analytic Accounts')
    partner_ids = fields.Many2many('res.partner',
                                   'ifrs_partner_rel',
                                   'ifrs_lines_id',
                                   'partner_id',
                                   string='Partners')
    tax_code_ids = fields.Many2many('account.tax.code',
                                    'ifrs_tax_rel',
                                    'ifrs_lines_id',
                                    'tax_code_id',
                                    string='Tax Codes')
    filter_id = fields.Many2one(
        'ir.filters',
        string='Custom Filter',
        ondelete='set null',
        domain=("[('model_id','=','account.move.line')]"))
    parent_id = fields.Many2one(
        'ifrs.lines',
        string='Parent',
        ondelete='set null',
        domain=("[('ifrs_id','=',parent.id),"
                "('type','=','total'),('id','!=',id)]"))
    operand_ids = fields.Many2many('ifrs.lines',
                                   'ifrs_operand_rel',
                                   'ifrs_parent_id',
                                   'ifrs_child_id',
                                   string='Second Operand')
    operator = fields.Selection(
        [('subtract', 'Subtraction'), ('condition', 'Conditional'),
         ('percent', 'Percentage'), ('ratio', 'Ratio'), ('product', 'Product'),
         ('without', 'First Operand Only')],
        string='Operator',
        required=False,
        default='without',
        help='Leaving blank will not take into account Operands')
    logical_operation = fields.Selection(
        LOGICAL_OPERATIONS,
        string='Logical Operations',
        required=False,
        help=('Select type of Logical Operation to perform with First '
              '(Left) and Second (Right) Operand'))
    logical_true = fields.Selection(
        LOGICAL_RESULT,
        string='Logical True',
        required=False,
        help=('Value to return in case Comparison is True'))
    logical_false = fields.Selection(
        LOGICAL_RESULT,
        string='Logical False',
        required=False,
        help=('Value to return in case Comparison is False'))
    comparison = fields.Selection(
        [('subtract', 'Subtraction'), ('percent', 'Percentage'),
         ('ratio', 'Ratio'), ('without', 'No Comparison')],
        string='Make Comparison',
        required=False,
        default='without',
        help=('Make a Comparison against the previous period.\nThat is, '
              'period X(n) minus period X(n-1)\nLeaving blank will not '
              'make any effects'))
    acc_val = fields.Selection([('init', 'Initial Values'),
                                ('var', 'Variation in Periods'),
                                ('fy', ('Ending Values'))],
                               string='Accounting Span',
                               required=False,
                               default='fy',
                               help='Leaving blank means YTD')
    value = fields.Selection([('debit', 'Debit'), ('credit', 'Credit'),
                              ('balance', 'Balance')],
                             string='Accounting Value',
                             required=False,
                             default='balance',
                             help='Leaving blank means Balance')
    total_ids = fields.Many2many('ifrs.lines',
                                 'ifrs_lines_rel',
                                 'parent_id',
                                 'child_id',
                                 string='First Operand')
    inv_sign = fields.Boolean(string='Change Sign to Amount',
                              default=False,
                              copy=True,
                              help='Allows you to show the help in the form')
    invisible = fields.Boolean(
        string='Invisible',
        default=False,
        copy=True,
        help='Allows whether the line of the report is printed or not')
    comment = fields.Text(string='Comments/Question',
                          help='Comments or questions about this ifrs line')

    _sql_constraints = [
        ('sequence_ifrs_id_unique', 'unique(sequence, ifrs_id)',
         'The sequence already have been set in another IFRS line')
    ]

    def _get_level(self, cr, uid, lll, tree, level=1, context=None):
        """ Calcula los niveles de los ifrs.lines, tomando en cuenta que sera
        un mismo arbol para los campos total_ids y operand_ids.
        @param lll: objeto a un ifrs.lines
        @param level: Nivel actual de la recursion
        @param tree: Arbol de dependencias entre lineas construyendose
        """
        context = context and dict(context) or {}
        if not tree.get(level):
            tree[level] = {}
        # The search through level should be backwards from the deepest level
        # to the outmost level
        levels = tree.keys()
        levels.sort()
        levels.reverse()
        xlevel = False
        for nnn in levels:
            xlevel = isinstance(tree[nnn].get(lll.id), (set)) and nnn or xlevel
        if not xlevel:
            tree[level][lll.id] = set()
        elif xlevel < level:
            tree[level][lll.id] = tree[xlevel][lll.id]
            del tree[xlevel][lll.id]
        else:  # xlevel >= level
            return True
        for jjj in set(lll.total_ids + lll.operand_ids):
            tree[level][lll.id].add(jjj.id)
            self._get_level(cr, uid, jjj, tree, level + 1, context=context)
        return True
示例#2
0
class Reportscraped(models.TransientModel):
    _name = 'report.scraped'

    product_product = fields.Many2many('product.product', string='Product')
    partner_id = fields.Many2one('res.partner', 'Customer')
    sale_order = fields.Many2one('sale.order', 'Sale order')
    start_date = fields.Date('From')
    end_date = fields.Date('To')

    def _get_res_from_sql(self):
        user_id = self._context['uid']
        select_statement = """
            select s.id as sale_id,
                s.partner_id as customer_id,
                p.id as product_name,
                rr.name as process_name,
                sum(r.finished_qty) as finished_qty,
                sum(r.scraped_qty) as scraped_qty,
                rr.code as process_code
        """

        from_statement = """
            from mrp_production mo
                join mrp_production_workcenter_line wol
                    on mo.id = wol.production_id
                left join mrp_workcenter_line_reporting r
                    on wol.id = r.workcenter_line_id
                join product_product p
                    on mo.product_id = p.id
                join res_users u
                    on u.id = %s
                join mrp_workcenter mw
                    on mw.id = wol.workcenter_id
                join resource_resource rr
                    on mw.resource_id = rr.id
                left join sale_order s
                    on position(
                        s.name || ':' in mo.origin) > 0
        """ % user_id

        where_statement = 'where mo.company_id = u.company_id'
        if self.start_date and self.end_date:
            where_statement = """
                where
                    wol.date_start >= cast('%s' as date)
                    and wol.date_start <= cast('%s' as date)
                    and mo.company_id = u.company_id
            """ % (self.start_date, self.end_date)
        elif self.start_date and not self.end_date:
            where_statement = """
                where
                    wol.date_start >= cast('%s' as date)
                    and mo.company_id = u.company_id
            """ % self.start_date
        elif not self.start_date and self.end_date:
            where_statement = """
                where
                    wol.date_start <= cast('%s' as date)
                    and mo.company_id = u.company_id
            """ % self.end_date

        group_statement = """
            group by s.id,
                 s.partner_id,
                 p.id,
                 rr.name,
                 rr.code
        """

        order_statement = """
            order by
                sale_id, product_name, process_code, process_name
        """

        psql_statement = """
            select sale_id,
                   customer_id,
                   product_name,
                   process_name,
                   scraped_qty,
                   finished_qty,
                   process_code
            from
                (%s %s %s %s) as l
            where
                finished_qty + scraped_qty > 0
            %s;
        """ % (select_statement, from_statement, where_statement,
               group_statement, order_statement)

        self._cr.execute(psql_statement)

        return self._cr.fetchall()

    def _get_workcenters_name(self):
        workcenters = sorted(self.env['mrp.workcenter'].search([]),
                             key=lambda rec: rec['code'])

        return [workcenter.name for workcenter in workcenters]

    def _is_product_id_not_in_ids(self, id):
        if self.product_product:
            for product in self.product_product:
                if product.id == id:
                    return False
            return True

        return False

    def _get_product_attributes(self, res, ids):
        if not res:
            return {}

        products = self.env['product.product'].search([('id', 'in', ids)])

        vals = {}
        for product in products:
            vals[product.id] = {
                'bottom': "",
                'inside': "",
                'outside': "",
            }
            for attribue_line_id in product.attribute_line_ids:
                if attribue_line_id.attribute_id:
                    if attribue_line_id.value_ids:
                        if attribue_line_id.attribute_id.name == u'Bottom':
                            vals[product.id]['bottom'] = \
                                attribue_line_id.value_ids.name
                        if attribue_line_id.attribute_id.name == u'\
                        Inner coating':
                            vals[product.id]['inside'] = \
                                attribue_line_id.value_ids.name
                        if attribue_line_id.attribute_id.name == u'\
                        Exterior coating':
                            vals[product.id]['outside'] = \
                                attribue_line_id.value_ids.name
        return vals

    def _get_lines_write_excel(self):
        res = self._get_res_from_sql()
        product_ids = list(set([line[2] for line in res]))
        attributes = self._get_product_attributes(res, product_ids)

        vals = {}
        for record in res:
            name = record[0] or False
            customer = record[1] or False
            product = record[2]
            process = record[3]
            scraped_qty = record[4] or 0
            finished_qty = record[5] or 0

            if self.sale_order and self.sale_order.id != name:
                continue

            if self.partner_id and self.partner_id.id != customer:
                continue

            if self._is_product_id_not_in_ids(product):
                continue

            if name:
                name = self.env['sale.order'].browse(name).name
            else:
                name = ""

            if customer:
                customer = self.env['res.partner'].browse(customer).name
            else:
                customer = ""

            product_name = self.env['product.product'].browse(product).name

            key = str(product) + ":" + name

            if key in vals.keys():
                if process in vals[key]['process']:
                    vals[key]['quantity'] += finished_qty
                    vals[key]['scraped_qty'][process] += scraped_qty
                    vals[key]['total_scraped'] += scraped_qty
                    pencertage = round(
                        vals[key]['total_scraped'] /
                        (vals[key]['quantity'] + vals[key]['\
                        total_scraped']) * 100, 2)
                    vals[key]['scraped_percentage'] = pencertage
                else:
                    vals[key]['quantity'] = finished_qty
                    vals[key]['process'].append(process)
                    vals[key]['scraped_qty'][process] = scraped_qty
                    vals[key]['total_scraped'] += scraped_qty
                    pencertage = round(
                        vals[key]['total_scraped'] /
                        (finished_qty + vals[key]['total_scraped']) * 100, 2)
                    vals[key]['scraped_percentage'] = pencertage
            else:
                pencertage = round(
                    scraped_qty / (scraped_qty + finished_qty) * 100, 2)
                vals[key] = {
                    'name': name,
                    'customer': customer,
                    'product': product_name,
                    'quantity': finished_qty,
                    'process': [process],
                    'scraped_qty': {
                        process: scraped_qty
                    },
                    'total_scraped': scraped_qty,
                    'scraped_percentage': pencertage
                }

                vals[key]['bottom'] = attributes[product]['bottom']
                vals[key]['inside'] = attributes[product]['inside']
                vals[key]['outside'] = attributes[product]['outside']

        return vals

    def _get_process_len(self, vals):
        length = 0

        for key, val in vals.items():
            if len(val['process']) > length:
                length = len(val['process'])

        return length

    def _get_table_titile(self, process_len):
        # save the format in col:title
        title = {
            u'0': u"Sales Order",
            u'1': u"Customer",
            u'2': u"Products",
            u'3': u"Bottom",
            u'4': u"Inner coating",
            u'5': u"Exterior coating",
            u'6': u"Quantity completion",
            u'7': u"Total scrap amount",
            u'8': u"Scrappage",
        }

        index = 9

        for name in self._get_workcenters_name():
            title[index] = name
            index = index + 1

        return title

    @api.multi
    def print_report(self):
        vals = self._get_lines_write_excel()
        process_len = self._get_process_len(vals)
        title = self._get_table_titile(process_len)

        datas = {'model': 'report.scraped', 'title': title, 'records': vals}

        return {
            'type': 'ir.actions.report.xml',
            'report_name': 'mrp.scraped.xls',
            'datas': datas
        }
示例#3
0
class Session(models.Model):
    _name = 'openacademy.session'

    name = fields.Char(required=True)
    start_date = fields.Date(default=fields.Date.today)
    duration = fields.Float(digit=(6, 2), help="Duration in days")
    seats = fields.Integer(string="Number of Seats")
    active = fields.Boolean(default=True)
    color = fields.Integer()

    instructor_id = fields.Many2one('res.partner',
                                    string='Instructor',
                                    domain=[
                                        '|', ('instructor', '=', True),
                                        ('category_id.name', 'ilike',
                                         "Teacher")
                                    ])
    course_id = fields.Many2one('openacademy.course',
                                ondelte='cascade',
                                string='Course',
                                required=True)
    attendee_ids = fields.Many2many('res.partner', string="Attendees")

    taken_seats = fields.Integer(string='Taken seats', compute='_taken_seats')
    end_date = fields.Date(string="End Date",
                           store=True,
                           compute='_get_end_date',
                           inverse='_set_end_date')

    hours = fields.Float(string="Duration in hours",
                         compute='_get_hours',
                         inverse='_set_hours')

    attendees_count = fields.Integer(string="Attendee count",
                                     compute="_get_attendees_count",
                                     store=True)

    state = fields.Selection([
        ('draft', "Draft"),
        ('confirmed', "Confirmed"),
        ('done', "Done"),
    ])

    @api.one
    def action_draft(self):
        self.state = 'draft'

    @api.one
    def action_confirm(self):
        self.state = 'confirmed'

    @api.one
    def action_done(self):
        self.state = 'done'

    @api.one
    @api.depends('seats', 'attendee_ids')
    def _taken_seats(self):
        if not self.seats:
            self.taken_seats = 0.0
        else:
            self.taken_seats = 100.0 * len(self.attendee_ids) / self.seats

    @api.onchange('seats', 'attendee_ids')
    def _verify_valid_seats(self):
        if self.seats < 0:
            return {
                'warning': {
                    'title':
                    _("Incorrect 'seats' value"),
                    'message':
                    _("The number of available seats may not be negative"),
                },
            }
        if self.seats < len(self.attendee_ids):
            return {
                'warning': {
                    'title': _("Too many attendees"),
                    'message': _("Increase seats or remove excess attendees"),
                },
            }

    @api.one
    @api.depends('start_date', 'duration')
    def _get_end_date(self):
        if not (self.start_date and self.duration):
            self.end_date = self.start_date
            return
        # Add duration to start_date, but: Monday + 5 days = Saturday, so
        # subtract one second to get on Friday instead
        start = fields.Datetime.from_string(self.start_date)
        duration = timedelta(days=self.duration, seconds=-1)
        self.end_date = start + duration

    @api.one
    def _set_end_date(self):
        if not (self.start_date and self.end_date):
            return
        # Compute the difference between dates, but: Friday - Monday = 4 days,
        # so add one day to get 5 days instead

        start_date = fields.Datetime.from_string(self.start_date)
        end_date = fields.Datetime.from_string(self.end_date)
        self.duration = (end_date - start_date).days + 1

    @api.one
    @api.depends('duration')
    def _get_hours(self):
        self.hours = self.duration * 24

    @api.one
    def _set_hours(self):
        self.duration = self.hours / 24

    @api.one
    @api.depends('attendee_ids')
    def _get_attendees_count(self):
        self.attendees_count = len(self.attendee_ids)

    @api.one
    @api.constrains('instructor_id', 'attendee_ids')
    def _check_instructor_not_in_attendees(self):
        if self.instructor_id and (self.instructor_id in self.attendee_ids):
            raise exceptions.ValidationError(
                _("A session's instructor can't be an attendee"))
示例#4
0
class L10nEsAeatMod347PartnerRecord(models.Model):
    _name = 'l10n.es.aeat.mod347.partner_record'
    _description = 'Partner Record'
    _rec_name = "partner_vat"

    @api.model
    def _default_record_id(self):
        return self.env.context.get('report_id', False)

    report_id = fields.Many2one(
        comodel_name='l10n.es.aeat.mod347.report',
        string='AEAT 347 Report',
        ondelete="cascade",
        default=_default_record_id,
    )
    operation_key = fields.Selection(
        selection=[
            ('A', u'A - Adquisiciones de bienes y servicios superiores al '
             u'límite (1)'),
            ('B',
             u'B - Entregas de bienes y servicios superiores al límite (1)'),
            ('C',
             u'C - Cobros por cuenta de terceros superiores al límite (3)'),
            ('D', u'D - Adquisiciones efectuadas por Entidades Públicas '
             u'(...) superiores al límite (1)'),
            ('E', u'E - Subvenciones, auxilios y ayudas satisfechas por Ad. '
             u'Públicas superiores al límite (1)'),
            ('F', u'F - Ventas agencia viaje'),
            ('G', u'G - Compras agencia viaje'),
        ],
        string='Operation Key',
    )
    partner_id = fields.Many2one(comodel_name='res.partner',
                                 string='Partner',
                                 required=True)
    partner_vat = fields.Char(string='VAT number', size=9)
    representative_vat = fields.Char(string='L.R. VAT number',
                                     size=9,
                                     help="Legal Representative VAT number")
    community_vat = fields.Char(
        string='Community vat number',
        size=17,
        help="VAT number for professionals established in other state "
        "member without national VAT")
    partner_country_code = fields.Char(string='Country Code', size=2)
    partner_state_code = fields.Char(string='State Code', size=2)
    first_quarter = fields.Float(
        string="First quarter operations",
        digits=dp.get_precision('Account'),
        help="Total amount of first quarter in, out and refund invoices "
        "for this partner",
        readonly=True,
    )
    first_quarter_real_estate_transmission_amount = fields.Float(
        string="First quarter real estate",
        digits=dp.get_precision('Account'),
        help="Total amount of first quarter real estate transmissions "
        "for this partner",
    )
    first_quarter_cash_amount = fields.Float(
        string="First quarter cash movements",
        readonly=True,
        digits=dp.get_precision('Account'),
        help="Total amount of first quarter cash movements for this partner",
    )
    second_quarter = fields.Float(
        string="Second quarter operations",
        digits=dp.get_precision('Account'),
        help="Total amount of second quarter in, out and refund invoices "
        "for this partner",
        readonly=True,
    )
    second_quarter_real_estate_transmission_amount = fields.Float(
        string="Second quarter real estate",
        digits=dp.get_precision('Account'),
        help="Total amount of second quarter real estate transmissions "
        "for this partner",
    )
    second_quarter_cash_amount = fields.Float(
        string="Second quarter cash movements",
        readonly=True,
        digits=dp.get_precision('Account'),
        help="Total amount of second quarter cash movements for this partner",
    )
    third_quarter = fields.Float(
        string="Third quarter operations",
        digits=dp.get_precision('Account'),
        help="Total amount of third quarter in, out and refund invoices "
        "for this partner",
        readonly=True,
    )
    third_quarter_real_estate_transmission_amount = fields.Float(
        string="Third quarter real estate",
        digits=dp.get_precision('Account'),
        help="Total amount of third quarter real estate transmissions "
        "for this partner",
    )
    third_quarter_cash_amount = fields.Float(
        string="Third quarter cash movements",
        readonly=True,
        digits=dp.get_precision('Account'),
        help="Total amount of third quarter cash movements for this partner",
    )
    fourth_quarter = fields.Float(
        string="Fourth quarter operations",
        digits=dp.get_precision('Account'),
        help="Total amount of fourth quarter in, out and refund invoices "
        "for this partner",
        readonly=True,
    )
    fourth_quarter_real_estate_transmission_amount = fields.Float(
        string="Fourth quarter real estate",
        digits=dp.get_precision('Account'),
        help="Total amount of fourth quarter real estate transmissions "
        "for this partner")
    fourth_quarter_cash_amount = fields.Float(
        string="Fourth quarter cash movements",
        readonly=True,
        digits=dp.get_precision('Account'),
        help="Total amount of fourth quarter cash movements for this partner",
    )
    amount = fields.Float(string='Operations amount', digits=(13, 2))
    cash_amount = fields.Float(string='Received cash amount', digits=(13, 2))
    real_estate_transmissions_amount = fields.Float(
        string='Real Estate Transmisions amount',
        digits=(13, 2),
    )
    insurance_operation = fields.Boolean(
        string='Insurance Operation',
        help="Only for insurance companies. Set to identify insurance "
        "operations aside from the rest.",
    )
    cash_basis_operation = fields.Boolean(
        string='Cash Basis Operation',
        help="Only for cash basis operations. Set to identify cash basis "
        "operations aside from the rest.",
    )
    tax_person_operation = fields.Boolean(
        string='Taxable Person Operation',
        help="Only for taxable person operations. Set to identify taxable "
        "person operations aside from the rest.",
    )
    related_goods_operation = fields.Boolean(
        string='Related Goods Operation',
        help="Only for related goods operations. Set to identify related "
        "goods operations aside from the rest.",
    )
    bussiness_real_estate_rent = fields.Boolean(
        string='Bussiness Real Estate Rent',
        help="Set to identify real estate rent operations aside from the rest."
        " You'll need to fill in the real estate info only when you are "
        "the one that receives the money.",
    )
    origin_year = fields.Integer(
        string='Origin year',
        help="Origin cash operation year",
    )
    invoice_record_ids = fields.One2many(
        comodel_name='l10n.es.aeat.mod347.invoice_record',
        inverse_name='partner_record_id',
        string='Invoice records',
    )
    real_estate_record_ids = fields.Many2many(
        compute="_compute_real_estate_record_ids",
        comodel_name="l10n.es.aeat.mod347.real_estate_record",
        string='Real Estate Records',
    )
    cash_record_ids = fields.One2many(
        comodel_name='l10n.es.aeat.mod347.cash_record',
        inverse_name='partner_record_id',
        string='Payment records',
    )
    check_ok = fields.Boolean(
        compute="_compute_check_ok",
        string='Record is OK',
        store=True,
        readonly=True,
        help='Checked if this record is OK',
    )

    @api.multi
    def _compute_real_estate_record_ids(self):
        """Get the real estate records from this record parent report for this
        partner.
        """
        self.real_estate_record_ids = self.env[
            'l10n.es.aeat.mod347.real_estate_record']
        if self.partner_id:
            self.real_estate_record_ids = self.real_estate_record_ids.search([
                ('report_id', '=', self.report_id.id),
                ('partner_id', '=', self.partner_id.id)
            ])

    @api.multi
    @api.depends('partner_country_code', 'partner_state_code', 'partner_vat',
                 'community_vat')
    def _compute_check_ok(self):
        for record in self:
            record.check_ok = (record.partner_country_code
                               and record.partner_state_code
                               and record.partner_state_code.isdigit()
                               and (record.partner_vat
                                    or record.partner_country_code != 'ES'))

    @api.onchange('partner_id')
    def onchange_partner_id(self):
        """Loads some partner data (country, state and vat) when the selected
        partner changes.
        """
        if self.partner_id:
            addr = self.partner_id.address_get(['delivery', 'invoice'])
            # Get the invoice or the default address of the partner
            addr = self.partner_id.address_get(['invoice', 'default'])
            address = self.env['res.partner'].browse(addr['invoice'])
            self.partner_vat = self.partner_id.vat and \
                re.match("(ES){0,1}(.*)",
                         self.partner_id.vat).groups()[1]
            self.partner_state_code = address.state_id.code
            self.partner_country_code = address.country_id.code
        else:
            self.partner_vat = ''
            self.partner_country_code = ''
            self.partner_state_code = ''

    @api.multi
    @api.depends('invoice_record_ids.invoice_id.date', 'report_id.year')
    def calculate_quarter_totals(self):
        def calc_amount_by_quarter(invoices, refunds, year, month_start):
            day_start = 1
            month_end = month_start + 2
            day_end = monthrange(year, month_end)[1]
            date_start = fields.Date.to_string(
                datetime(year, month_start, day_start))
            date_end = fields.Date.to_string(datetime(year, month_end,
                                                      day_end))
            return (sum(
                invoices.filtered(lambda x: date_start <= x.invoice_id.date <=
                                  date_end).mapped('amount')) -
                    sum(
                        refunds.filtered(lambda x: date_start <= x.invoice_id.
                                         date <= date_end).mapped('amount')))

        for record in self:
            year = record.report_id.year
            invoices = record.invoice_record_ids.filtered(lambda rec: (
                rec.invoice_id.type in ('out_invoice', 'in_invoice')))
            refunds = record.invoice_record_ids.filtered(lambda rec: (
                rec.invoice_id.type in ('out_refund', 'in_refund')))
            record.first_quarter = calc_amount_by_quarter(
                invoices,
                refunds,
                year,
                1,
            )
            record.second_quarter = calc_amount_by_quarter(
                invoices,
                refunds,
                year,
                4,
            )
            record.third_quarter = calc_amount_by_quarter(
                invoices,
                refunds,
                year,
                7,
            )
            record.fourth_quarter = calc_amount_by_quarter(
                invoices,
                refunds,
                year,
                10,
            )

    @api.multi
    def calculate_quarter_cash_totals(self):
        def calc_amount_by_quarter(records, year, month_start):
            day_start = 1
            month_end = month_start + 2
            day_end = monthrange(year, month_end)[1]
            date_start = fields.Date.to_string(
                datetime(year, month_start, day_start))
            date_end = fields.Date.to_string(datetime(year, month_end,
                                                      day_end))
            return sum(
                records.filtered(lambda x: date_start <= x.invoice_id.date <=
                                 date_end).mapped('amount'))

        for record in self:
            if not record.cash_record_ids:
                continue
            year = record.report_id.year
            record.first_quarter_cash_amount = calc_amount_by_quarter(
                record.cash_record_ids,
                year,
                1,
            )
            record.second_quarter_cash_amount = calc_amount_by_quarter(
                record.cash_record_ids,
                year,
                4,
            )
            record.third_quarter_cash_amount = calc_amount_by_quarter(
                record.cash_record_ids,
                year,
                7,
            )
            record.fourth_quarter_cash_amount = calc_amount_by_quarter(
                record.cash_record_ids,
                year,
                10,
            )
            # Totals
            record.cash_amount = sum([
                record.first_quarter_cash_amount,
                record.second_quarter_cash_amount,
                record.third_quarter_cash_amount,
                record.fourth_quarter_cash_amount
            ])
示例#5
0
class JasperReportReceivableConfirmationLetter(models.TransientModel):
    _name = 'receivable.confirmation.letter'
    _inherit = 'report.account.common'

    fiscalyear_start_id = fields.Many2one(default=False, )
    fiscalyear_end_id = fields.Many2one(default=False, )
    filter = fields.Selection(
        readonly=True,
        default='filter_date',
    )
    date_report = fields.Date(
        string='Report Date',
        required=True,
        default=lambda self: fields.Date.context_today(self),
    )
    account_ids = fields.Many2many(
        'account.account',
        string='Accounts',
        domain=[('type', '=', 'receivable')],
    )
    partner_ids = fields.Many2many(
        'res.partner',
        string='Customers',
        domain=[('customer', '=', True)],
    )

    @api.multi
    def _get_report_name(self):
        self.ensure_one()
        report_name = "receivable_confirmation_letter"
        return report_name

    @api.multi
    def _get_sql_condition(self):
        self.ensure_one()
        condition = "a.type = 'receivable'"
        if self.account_ids:
            if len(self.account_ids) > 1:
                condition += \
                    " AND a.id IN %s" % (str(tuple(self.account_ids.ids)), )
            else:
                condition += "AND a.id = %s" % (self.account_ids.id, )
        if self.partner_ids:
            if len(self.partner_ids) > 1:
                condition += " AND l.partner_id IN %s" \
                    % (str(tuple(self.partner_ids.ids)), )
            else:
                condition += " AND l.partner_id = %s" % (self.partner_ids.id, )
        # Check for History View
        condition += " AND l.date_created <= '%s' \
                      AND (l.reconcile_id IS NULL OR \
                      l.date_reconciled > '%s')" \
                      % (self.date_report, self.date_report, )
        return condition

    @api.multi
    def _get_move_line_ids(self):
        self.ensure_one()
        self._cr.execute("""
            SELECT l.id
            FROM account_move_line l
            LEFT JOIN account_account a ON l.account_id = a.id
            WHERE %s""" % (self._get_sql_condition(), ))
        move_line_ids = list(map(lambda l: l[0], self._cr.fetchall()))
        # If not found data
        if not move_line_ids:
            raise ValidationError(_('No Data!'))
        return move_line_ids

    @api.multi
    def _get_datas(self):
        self.ensure_one()
        data = {'parameters': {}}
        data['parameters']['ids'] = self._get_move_line_ids()
        date_report = datetime.strptime(self.date_report, '%Y-%m-%d')
        data['parameters']['date_report'] = date_report.strftime('%d/%m/%Y')
        data['parameters']['date_run'] = time.strftime('%d/%m/%Y')
        data['parameters']['company_name'] = \
            self.company_id.partner_id.with_context(lang="th_TH").name
        return data

    @api.multi
    def run_report(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.report.xml',
            'report_name': self._get_report_name(),
            'datas': self._get_datas(),
        }
示例#6
0
class add_hours_wizard(models.TransientModel):
    _name = "add_hours.wizard"

    def _default_partner(self):
        #		pdb.set_trace()
        return self.env['account.invoice'].browse(
            self.env['account.invoice']._context.get('active_id')).partner_id

    def _default_hours_ids(self):
        search_domain = [('account_id.partner_id', '=',
                          self.env['account.invoice'].browse(
                              self._context.get('active_id')).partner_id.id)]
        search_domain = search_domain + [('invoice_id', '=', False)]
        search_domain = search_domain + [('to_invoice', '!=', False)]

        return self.env['account.analytic.line'].search(search_domain)

    def _default_invoice(self):
        #pdb.set_trace()
        return self.env['account.invoice'].browse(
            self.env['account.invoice']._context.get('active_id'))

    def _default_product(self):
        #pdb.set_trace()
        return self.env['account.invoice'].browse(
            self.env['account.invoice']._context.get(
                'active_id')).company_id.default_hours_product

    partner_id = fields.Many2one('res.partner',
                                 string="Customer",
                                 readonly=True,
                                 default=_default_partner)
    product_id = fields.Many2one('product.product',
                                 string="Product",
                                 required=True,
                                 default=_default_product)
    invoice_id = fields.Many2one('account.invoice',
                                 readonly=True,
                                 string="Invoice",
                                 default=_default_invoice)
    hours_ids = fields.Many2many("account.analytic.line",
                                 default=_default_hours_ids)

    @api.multi
    def add_hours_to_invoice(self):
        #		obj_invoice_lines=self.invoice_id.create({'product_id':self.product_id})
        total = 0
        for l in self.hours_ids:
            l._calculate_invoicable()
            total = total + l.amount_total
        obj_invoice_lines = self.env['account.invoice.line']
        #		pdb.set_trace()
        invoice_line = {
            ('price_unit', total),
            ('invoice_id', self.invoice_id.id),
            ('name', self.product_id.name),
            ('product_id', self.product_id.id),
            ('uos_id', self.product_id.uom_id.id),
            ('account_analytic_id', l.account_id.id),
            ('account_id', self.product_id.property_account_income.id
             | self.product_id.categ_id.property_account_income_categ.id),
            #('invoice_line_tax_id',[(6, 0, self.product_id.taxes_id)]),
        }

        #pdb.set_trace()
        obj_invoice_lines = obj_invoice_lines.create(invoice_line)

        obj_invoice_lines.invoice_line_tax_id = self.env[
            'account.fiscal.position'].browse(
                self.invoice_id.fiscal_position.id).map_tax(
                    self.product_id.taxes_id)
        for l in self.hours_ids:
            l.write({'invoice_id': self.invoice_id.id})


#		self.write([l.id for l in self.hours_ids], {'invoice_id': self.invoice_id.id})
        self.env['account.invoice'].browse(
            self.invoice_id.id).button_reset_taxes()
示例#7
0
class XLSXReportAsset(models.TransientModel):
    _name = 'xlsx.report.asset'
    _inherit = 'report.account.common'

    filter = fields.Selection(
        [('filter_date', 'Dates'),
         ('filter_period', 'Periods')],
        string='Filter by',
        required=True,
        default='filter_period',
    )
    asset_status_draft = fields.Boolean(
        string='Draft',
    )
    asset_status_open = fields.Boolean(
        string='Running',
    )
    asset_status_close = fields.Boolean(
        string='Close',
    )
    asset_status_removed = fields.Boolean(
        string='Removed',
    )
    asset_status = fields.Selection(
        [('draft', 'Draft'),
         ('open', 'Running'),
         ('close', 'Close'),
         ('removed', 'Removed')],
        string=' Asset Status'
    )
    asset_ids = fields.Many2many(
        'account.asset',
        string='Asset Code',
    )
    asset_profile_ids = fields.Many2many(
        'account.asset.profile',
        string='Asset Profile',
    )
    date_filter = fields.Char(
        compute='_compute_date_filter',
        string='Date Filter',
    )
    # Note: report setting
    accum_depre_account_type = fields.Many2one(
        'account.account.type',
        string='Account Type for Accum.Depre.',
        required=True,
        help="Define account type for accumulated depreciation account, "
        "to be used in report query SQL."
    )
    depre_account_type = fields.Many2one(
        'account.account.type',
        string='Account Type for Depre.',
        required=True,
        help="Define account type for depreciation account, "
        "to be used in report query SQL."
    )
    results = fields.Many2many(
        'asset.view',
        string='Results',
        compute='_compute_results',
        help='Use compute fields, so there is nothing store in database',
    )

    @api.model
    def _domain_to_where_str(self, domain):
        """ Helper Function for better performance """
        where_dom = [" %s %s %s " % (x[0], x[1], isinstance(x[2], basestring)
                     and "'%s'" % x[2] or x[2]) for x in domain]
        where_str = 'and'.join(where_dom)
        return where_str

    @api.multi
    def _compute_results(self):
        self.ensure_one()
        dom = []
        status = []
        # Prepare DOM to filter assets
        if self.asset_status_draft:
            status += ['draft']
        if self.asset_status_open:
            status += ['open']
        if self.asset_status_close:
            status += ['close']
        if self.asset_status_removed:
            status += ['removed']
        if self.asset_ids:
            dom += [('id', 'in', tuple(self.asset_ids.ids + [0]))]
        if self.asset_profile_ids:
            dom += [('profile_id', 'in',
                    tuple(self.asset_profile_ids.ids + [0]))]
        if status:
            dom += [('state', 'in', tuple(status + ['']))]
        # Prepare fixed params
        date_start = False
        date_end = False
        # fiscalyear_start = self.fiscalyear_start_id.name
        if self.filter == 'filter_date':
            date_start = self.date_start
            date_end = self.date_end
        if self.filter == 'filter_period':
            date_start = self.period_start_id.date_start
            date_end = self.period_end_id.date_stop
        if not date_start or not date_end:
            raise ValidationError(_('Please provide from and to dates.'))
        accum_depre_account_ids = self.env['account.account'].search(
            [('user_type', '=', self.accum_depre_account_type.id)]).ids
        depre_account_ids = self.env['account.account'].search(
            [('user_type', '=', self.depre_account_type.id)]).ids
        where_str = self._domain_to_where_str(dom)
        if where_str:
            where_str = 'and ' + where_str
        self._cr.execute("""
            select a.*, id asset_id,
                -- depreciation
                (select coalesce(sum(debit-credit), 0.0)
                 from account_move_line ml
                 where account_id in %s  -- depreciation account
                 and ml.date between %s and %s
                 and asset_id = a.id) depreciation,
                -- accumulated_cf
                (select coalesce(sum(credit-debit), 0.0)
                 from account_move_line ml
                 where account_id in %s  -- accumulated account
                 and ml.date <= %s -- date end
                 and asset_id = a.id) accumulated_cf,
                -- accumulated_bf
                case when a.date_start >= %s
                then 0 else
                (select a.purchase_value - coalesce(sum(credit-debit), 0.0)
                 from account_move_line ml
                 join account_period ap on ap.id = ml.period_id
                 join account_fiscalyear af on af.id = ap.fiscalyear_id
                 where account_id in %s  -- accumulatedp account
                 and ml.date < %s
                 and asset_id = a.id) end accumulated_bf
            from
            account_asset a
            where (a.state != 'close' or a.value_depreciated != 0)
        """ + where_str + "order by profile_id, number",
                         (tuple(depre_account_ids), date_start, date_end,
                          tuple(accum_depre_account_ids), date_end,
                          date_start,
                          tuple(accum_depre_account_ids), date_start))
        asset_results = self._cr.dictfetchall()
        ReportLine = self.env['asset.view']
        for line in asset_results:
            self.results += ReportLine.new(line)

    @api.multi
    def _compute_date_filter(self):
        if self.filter == 'filter_date':
            date_start = self.date_start
            date_end = self.date_end
        elif self.filter == 'filter_period':
            date_start = self.period_start_id.date_start
            date_end = self.period_end_id.date_stop
        else:
            date_start = self.fiscalyear_start_id.date_start
            date_end = self.fiscalyear_end_id.date_stop
        self.date_filter = _(
            ('ตั้งแต่วันที่ %s ถึง %s') % (date_start, date_end))

    @api.multi
    def action_get_report(self):
        action = self.env.ref(
            'cmo_account_report.action_xlsx_report_asset_form')
        action.sudo().write({'context': {'wizard_id': self.id}})
        return super(XLSXReportAsset, self).action_get_report()

    @api.onchange('asset_status')
    def _onchange_asset_status(self):
        if self.asset_status:
            return {'domain': {'asset_ids': [
                ('state', '=', self.asset_status)]}}
        else:
            return {'domain': {'asset_ids': []}}
示例#8
0
class OpPublisher(models.Model):
    _name = 'op.publisher'

    name = fields.Char('Name', size=20, required=True)
    address_id = fields.Many2one('res.partner', 'Address')
    book_ids = fields.Many2many('op.book', string='Book(s)')
示例#9
0
class rappel(models.Model):

    _inherit = 'rappel'
    brand_ids = fields.Many2many('product.brand', 'rappel_product_brand_rel',
                                 'rappel_id', 'product_brand_id', 'Brand')
    discount_voucher = fields.Boolean('Discount voucher')
    pricelist_ids = fields.Many2many('product.pricelist',
                                     'rappel_product_pricelist_rel',
                                     'rappel_id', 'product_pricelist_id',
                                     'Pricelist')
    description = fields.Char('Description', translate=True)
    sequence = fields.Integer('Sequence', default=100)

    @api.multi
    def get_products(self):
        product_obj = self.env['product.product']
        product_ids = self.env['product.product']
        for rappel in self:
            if not rappel.global_application:
                if rappel.product_id:
                    product_ids += rappel.product_id
                elif rappel.brand_ids:
                    product_ids += product_obj.search([
                        ('product_brand_id', 'in', rappel.brand_ids.ids)
                    ])
                elif rappel.product_categ_id:
                    product_ids += product_obj.search([
                        ('categ_id', '=', rappel.product_categ_id.id)
                    ])
            else:
                product_ids += product_obj.search([])
        return product_ids.ids

    @api.constrains('global_application', 'product_id', 'brand_ids',
                    'product_categ_id')
    def _check_application(self):
        if not self.global_application and not self.product_id \
                and not self.product_categ_id and not self.brand_ids:
            raise exceptions. \
                ValidationError(_('Product, brand and category are empty'))

    @api.model
    def update_partner_rappel_pricelist(self):
        partner_obj = self.env['res.partner']
        rappel_obj = self.env['rappel']
        partner_rappel_obj = self.env['res.partner.rappel.rel']

        now = datetime.now()
        now_str = now.strftime("%Y-%m-%d")
        yesterday_str = (now - relativedelta(days=1)).strftime("%Y-%m-%d")
        end_actual_month = now.strftime("%Y-%m") + '-' + str(
            monthrange(now.year, now.month)[1])
        start_next_month = (now +
                            relativedelta(months=1)).strftime("%Y-%m") + '-01'

        discount_voucher_rappels = rappel_obj.search([('discount_voucher', '=',
                                                       True)])

        for rappel in discount_voucher_rappels:
            pricelist_ids = tuple(rappel.pricelist_ids.ids)
            partner_pricelist = tuple(
                partner_obj.search([('property_product_pricelist',
                                     'in', pricelist_ids),
                                    ('prospective', '=', False),
                                    ('active', '=', True),
                                    ('is_company', '=', True),
                                    ('parent_id', '=', False)]).ids)
            partner_rappel = tuple(
                partner_rappel_obj.search([('rappel_id', '=', rappel.id), '|',
                                           ('date_end', '=', False),
                                           ('date_end', '>=', now_str),
                                           ('date_start', '<=', now_str)
                                           ]).mapped('partner_id.id'))

            #  Clientes que faltan en el rappel -> Se crean dos entradas en el rappel:
            #      - Una para liquidar en el mes actual
            #      - Otra que empiece en fecha 1 del mes siguiente
            add_partners = set(partner_pricelist) - set(partner_rappel)
            if add_partners:
                new_line1 = {
                    'rappel_id': rappel.id,
                    'periodicity': 'monthly',
                    'date_start': now_str,
                    'date_end': end_actual_month
                }
                new_line2 = {
                    'rappel_id': rappel.id,
                    'periodicity': 'monthly',
                    'date_start': start_next_month
                }
                for partner in add_partners:
                    new_line1.update({'partner_id': partner})
                    partner_rappel_obj.create(new_line1)
                    new_line2.update({'partner_id': partner})
                    partner_rappel_obj.create(new_line2)

            # Clientes a los que ya no les corresponde el rappel -> Se actualiza fecha fin con la fecha actual
            remove_partners = set(partner_rappel) - set(partner_pricelist)
            if remove_partners:
                vals = {'date_end': yesterday_str}
                partner_to_update = partner_rappel_obj.search([
                    ('rappel_id', '=', rappel.id),
                    ('partner_id', 'in', tuple(remove_partners)), '|',
                    ('date_end', '=', False), ('date_end', '>', now),
                    ('date_start', '<=', now_str)
                ])
                partner_to_update.write(vals)

    @api.model
    def compute_rappel(self):
        if not self.ids:
            ordered_rappels = self.search([], order='sequence')
        else:
            ordered_rappels = self.sorted(key=lambda x: x.sequence)
        super(rappel, ordered_rappels).compute_rappel()
示例#10
0
class ReportEvaluationByTeacherWizard(models.TransientModel):
    _name = "school_evaluations.report_evaluation_by_teacher"
    _description = "Evaluations by Teacher Report"

    year_id = fields.Many2one(
        'school.year',
        string='Year',
        default=lambda self: self.env.user.current_year_id,
        ondelete='cascade')
    teacher_id = fields.Many2one('res.partner',
                                 string='Teacher',
                                 ondelete='cascade',
                                 domain=[('teacher', '=', True)])
    teacher_ids = fields.Many2many('res.partner',
                                   'report_evaluation_by_teacher_teacher_rel',
                                   'report_id',
                                   'teacher_id',
                                   string='Teachers',
                                   ondelete='cascade',
                                   domain=[('teacher', '=', True)])
    display_results = fields.Boolean(string='Display Current Results')
    freeze_first_session = fields.Boolean(string='Freeze First Session')
    message = fields.Text(string="Message")

    send_as_email = fields.Boolean(string="Send as email")

    @api.multi
    def print_report(self, data):
        self.ensure_one()
        data['year_id'] = self.year_id.id
        data['message'] = self.message
        data['display_results'] = self.display_results
        data['freeze_first_session'] = self.freeze_first_session
        if self.send_as_email:
            for teacher_id in self.teacher_ids:
                data['teacher_ids'] = [teacher_id.id]
                self.send_mail(teacher_id, data)
        else:
            if self.teacher_id:
                data['teacher_ids'] = [self.teacher_id.id]
            elif self.teacher_ids:
                data['teacher_ids'] = self.teacher_ids.ids
            else:
                context = dict(self._context or {})
                data['teacher_ids'] = data.get('active_ids')
            return self.env['report'].get_action(
                self,
                'school_evaluations.report_evaluation_by_teacher_content',
                data=data)

    def send_mail(self, teacher_id, data):
        """Generates a new mail message for the given template and record,
           and schedules it for delivery through the ``mail`` module's scheduler.
           :param int res_id: id of the record to render the template with
                              (model is taken from the template)
           :param bool force_send: if True, the generated mail.message is
                immediately sent after being created, as if the scheduler
                was executed for this message only.
           :returns: id of the mail.message that was created
        """
        self.ensure_one()
        Mail = self.env['mail.mail']
        Attachment = self.env[
            'ir.attachment']  # TDE FIXME: should remove dfeault_type from context

        template = self.env.ref(
            'school_evaluations.mail_template_evaluation_email')
        for wizard_line in self:
            if template:

                # create a mail_mail based on values, without attachments
                values = template.generate_email(teacher_id.id)
                values['recipient_ids'] = [(6, 0, [teacher_id.id])]
                attachment_ids = values.pop('attachment_ids', [])
                attachments = values.pop('attachments', [])

                # add a protection against void email_from
                if 'email_from' in values and not values.get('email_from'):
                    values.pop('email_from')

                mail = Mail.create(values)

                # manage attachments

                filename = "evaluations.pdf"

                report = self.env.ref(
                    'school_evaluations.report_evaluation_by_teacher')

                pdf_bin, _ = report.render_report(
                    [teacher_id.id],
                    'school_evaluations.report_evaluation_by_teacher_content',
                    data=data)

                attachment = self.env['ir.attachment'].create({
                    'name':
                    filename,
                    'datas':
                    base64.b64encode(pdf_bin),
                    'datas_fname':
                    filename,
                    'res_model':
                    'res.partner',
                    'res_id':
                    teacher_id.id,
                    'type':
                    'binary',  # override default_type from context, possibly meant for another model!
                })

                # for attachment in attachments:
                #     attachment_data = {
                #         'name': attachment[0],
                #         'datas_fname': attachment[0],
                #         'datas': attachment[1],
                #         'type': 'binary',
                #         'res_model': 'mail.message',
                #         'res_id': mail.mail_message_id.id,
                #     }
                #     attachment_ids.append(Attachment.create(attachment_data).id)
                # if attachment_ids:
                #     values['attachment_ids'] = [(6, 0, attachment_ids)]

                mail.write({'attachment_ids': [(6, 0, [attachment.id])]})

                mail.send()

                return mail.id  # TDE CLEANME: return mail + api.returns ?
示例#11
0
class ir_attahment(models.Model):
    _inherit = 'ir.attachment'

    tag_ids = fields.Many2many(comodel_name='ir.attachment.tag', string='Tags')
示例#12
0
文件: sale.py 项目: nitinitprof/odoo
class AccountInvoiceLine(models.Model):
    _inherit = 'account.invoice.line'
    sale_line_ids = fields.Many2many('sale.order.line', 'sale_order_line_invoice_rel', 'invoice_line_id', 'order_line_id', string='Sale Order Lines', readonly=True, copy=False)
示例#13
0
文件: sale.py 项目: nitinitprof/odoo
class SaleOrderLine(models.Model):
    _name = 'sale.order.line'
    _description = 'Sales Order Line'
    _order = 'order_id desc, sequence, id'

    @api.depends('state', 'product_uom_qty', 'qty_delivered', 'qty_to_invoice', 'qty_invoiced')
    def _compute_invoice_status(self):
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        for line in self:
            if line.state not in ('sale', 'done'):
                line.invoice_status = 'no'
            elif not float_is_zero(line.qty_to_invoice, precision_digits=precision):
                line.invoice_status = 'to invoice'
            elif float_compare(line.qty_invoiced, line.product_uom_qty, precision_digits=precision) == 1 or\
                    float_compare(line.qty_invoiced, line.product_uom_qty, precision_digits=precision) >= 0 and\
                    float_compare(line.qty_delivered, line.product_uom_qty, precision_digits=precision) == 1:
                line.invoice_status = 'upselling'
            elif float_compare(line.qty_invoiced, line.product_uom_qty, precision_digits=precision) == 0:
                line.invoice_status = 'invoiced'
            else:
                line.invoice_status = 'no'

    @api.depends('product_uom_qty', 'discount', 'price_unit', 'tax_id')
    def _compute_amount(self):
        for line in self:
            price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
            taxes = line.tax_id.compute_all(price, line.order_id.currency_id, line.product_uom_qty, product=line.product_id, partner=line.order_id.partner_id)
            line.update({
                'price_tax': taxes['total_included'] - taxes['total_excluded'],
                'price_total': taxes['total_included'],
                'price_subtotal': taxes['total_excluded'],
            })

    @api.depends('product_id.invoice_policy', 'order_id.state')
    def _compute_qty_delivered_updateable(self):
        for line in self:
            line.qty_delivered_updateable = line.product_id.invoice_policy in ('order', 'delivery') and line.order_id.state == 'sale'

    @api.depends('qty_invoiced', 'qty_delivered', 'product_uom_qty', 'order_id.state')
    def _get_to_invoice_qty(self):
        for line in self:
            if line.order_id.state in ['sale', 'done']:
                if line.product_id.invoice_policy == 'order':
                    line.qty_to_invoice = line.product_uom_qty - line.qty_invoiced
                else:
                    line.qty_to_invoice = line.qty_delivered - line.qty_invoiced
            else:
                line.qty_to_invoice = 0

    @api.depends('invoice_lines.invoice_id.state', 'invoice_lines.quantity')
    def _get_invoice_qty(self):
        for line in self:
            qty_invoiced = 0.0
            for invoice_line in line.invoice_lines:
                if invoice_line.invoice_id.state != 'cancel':
                    if invoice_line.invoice_id.type == 'out_invoice':
                        qty_invoiced += invoice_line.quantity
                    elif invoice_line.invoice_id.type == 'out_refund':
                        qty_invoiced -= invoice_line.quantity
            line.qty_invoiced = qty_invoiced

    @api.depends('price_subtotal', 'product_uom_qty')
    def _get_price_reduce(self):
        for line in self:
            line.price_reduce = line.price_subtotal / line.product_uom_qty if line.product_uom_qty else 0.0

    @api.multi
    @api.onchange('order_id', 'product_id')
    def _compute_tax_id(self):
        for line in self:
            fpos = line.order_id.fiscal_position_id or line.order_id.partner_id.property_account_position_id
            if fpos:
                # The superuser is used by website_sale in order to create a sale order. We need to make
                # sure we only select the taxes related to the company of the partner. This should only
                # apply if the partner is linked to a company.
                if self.env.uid == SUPERUSER_ID and line.order_id.company_id:
                    taxes = fpos.map_tax(line.product_id.taxes_id).filtered(lambda r: r.company_id == line.order_id.company_id)
                else:
                    taxes = fpos.map_tax(line.product_id.taxes_id)
                line.tax_id = taxes
            else:
                line.tax_id = False

    @api.multi
    def _prepare_order_line_procurement(self, group_id=False):
        self.ensure_one()
        return {
            'name': self.name,
            'origin': self.order_id.name,
            'date_planned': datetime.strptime(self.order_id.date_order, DEFAULT_SERVER_DATETIME_FORMAT) + timedelta(days=self.customer_lead),
            'product_id': self.product_id.id,
            'product_qty': self.product_uom_qty,
            'product_uom': self.product_uom.id,
            'company_id': self.order_id.company_id.id,
            'group_id': group_id,
            'sale_line_id': self.id
        }

    @api.multi
    def _action_procurement_create(self):
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        for line in self:
            if line.state != 'sale':
                continue
            qty = 0.0
            for proc in line.procurement_ids:
                qty += proc.product_qty
            if float_compare(qty, line.product_uom_qty, precision_digits=precision) >= 0:
                return False

            if not line.order_id.procurement_group_id:
                vals = line.order_id._prepare_procurement_group()
                line.order_id.procurement_group_id = self.env["procurement.group"].create(vals)

            vals = line._prepare_order_line_procurement(group_id=line.order_id.procurement_group_id.id)
            vals['product_qty'] = line.product_uom_qty - qty
            new_proc = self.env["procurement.order"].create(vals)
            new_proc.run()
        return True

    @api.model
    def _get_analytic_invoice_policy(self):
        return ['cost']

    @api.model
    def _get_analytic_track_service(self):
        return []

    # Create new procurements if quantities purchased changes
    @api.model
    def create(self, values):
        line = super(SaleOrderLine, self).create(values)
        if line.state == 'sale':
            if line.product_id.track_service in self._get_analytic_track_service() or line.product_id.invoice_policy in self._get_analytic_invoice_policy() and not line.order_id.project_id:
                line.order_id._create_analytic_account()
            line._action_procurement_create()

        return line

    # Create new procurements if quantities purchased changes
    @api.multi
    def write(self, values):
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        lines = False
        if 'product_uom_qty' in values:
            lines = self.filtered(
                lambda r: r.state == 'sale' and float_compare(r.product_uom_qty, values['product_uom_qty'], precision_digits=precision) == -1)
            lines._action_procurement_create()
        return super(SaleOrderLine, self).write(values)

    order_id = fields.Many2one('sale.order', string='Order Reference', required=True, ondelete='cascade', index=True, copy=False)
    name = fields.Text(string='Description', required=True)
    sequence = fields.Integer(string='Sequence', default=10)

    invoice_lines = fields.Many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_line_id', string='Invoice Lines', copy=False)
    invoice_status = fields.Selection([
        ('upselling', 'Upselling Opportunity'),
        ('invoiced', 'Fully Invoiced'),
        ('to invoice', 'To Invoice'),
        ('no', 'Nothing to Invoice')
        ], string='Invoice Status', compute='_compute_invoice_status', store=True, readonly=True, default='no')
    price_unit = fields.Float('Unit Price', required=True, digits_compute=dp.get_precision('Product Price'), default=0.0)

    price_subtotal = fields.Monetary(compute='_compute_amount', string='Subtotal', readonly=True, store=True)
    price_tax = fields.Monetary(compute='_compute_amount', string='Taxes', readonly=True, store=True)
    price_total = fields.Monetary(compute='_compute_amount', string='Total', readonly=True, store=True)

    price_reduce = fields.Monetary(compute='_get_price_reduce', string='Price Reduce', readonly=True, store=True)
    tax_id = fields.Many2many('account.tax', string='Taxes', readonly=True, states={'draft': [('readonly', False)]})

    discount = fields.Float(string='Discount (%)', digits_compute=dp.get_precision('Discount'), default=0.0)

    product_id = fields.Many2one('product.product', string='Product', domain=[('sale_ok', '=', True)], change_default=True, ondelete='restrict', required=True)
    product_uom_qty = fields.Float(string='Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True, default=1.0)
    product_uom = fields.Many2one('product.uom', string='Unit of Measure', required=True)

    qty_delivered_updateable = fields.Boolean(compute='_compute_qty_delivered_updateable', string='Can Edit Delivered', readonly=True, default=True)
    qty_delivered = fields.Float(string='Delivered', copy=False, digits_compute=dp.get_precision('Product Unit of Measure'), default=0.0)
    qty_to_invoice = fields.Float(
        compute='_get_to_invoice_qty', string='To Invoice', store=True, readonly=True,
        digits_compute=dp.get_precision('Product Unit of Measure'), default=0.0)
    qty_invoiced = fields.Float(
        compute='_get_invoice_qty', string='Invoiced', store=True, readonly=True,
        digits_compute=dp.get_precision('Product Unit of Measure'), default=0.0)

    salesman_id = fields.Many2one(related='order_id.user_id', store=True, string='Salesperson', readonly=True)
    currency_id = fields.Many2one(related='order_id.currency_id', store=True, string='Currency', readonly=True)
    company_id = fields.Many2one(related='order_id.company_id', string='Company', store=True, readonly=True)
    order_partner_id = fields.Many2one(related='order_id.partner_id', store=True, string='Customer')

    state = fields.Selection([
        ('draft', 'Quotation'),
        ('sent', 'Quotation Sent'),
        ('sale', 'Sale Order'),
        ('done', 'Done'),
        ('cancel', 'Cancelled'),
    ], related='order_id.state', string='Order Status', readonly=True, copy=False, store=True, default='draft')

    customer_lead = fields.Float(
        'Delivery Lead Time', required=True, default=0.0,
        help="Number of days between the order confirmation and the shipping of the products to the customer", oldname="delay")
    procurement_ids = fields.One2many('procurement.order', 'sale_line_id', string='Procurements')

    @api.multi
    def _prepare_invoice_line(self, qty):
        """Prepare the dict of values to create the new invoice line for a
           sales order line. This method may be overridden to implement custom
           invoice generation (making sure to call super() to establish
           a clean extension chain).

           :param qty : float quantity to invoice
        """
        self.ensure_one()
        res = {}
        account_id = self.product_id.property_account_income_id.id or self.product_id.categ_id.property_account_income_categ_id.id
        if not account_id:
            raise UserError(_('Please define income account for this product: "%s" (id:%d) - or for its category: "%s".') % \
                            (self.product_id.name, self.product_id.id, self.product_id.categ_id.name))

        fpos = self.order_id.fiscal_position_id or self.order_id.partner_id.property_account_position_id
        if fpos:
            account_id = self.order_id.fiscal_position_id.map_account(account_id)

        res = {
            'name': self.name,
            'sequence': self.sequence,
            'origin': self.order_id.name,
            'account_id': account_id,
            'price_unit': self.price_unit,
            'quantity': qty,
            'discount': self.discount,
            'uom_id': self.product_uom.id,
            'product_id': self.product_id.id or False,
            'invoice_line_tax_ids': [(6, 0, self.tax_id.ids)],
            'account_analytic_id': self.order_id.project_id.id,
        }
        return res

    @api.multi
    def invoice_line_create(self, invoice_id, qty):
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        for line in self:
            if not float_is_zero(qty, precision_digits=precision):
                vals = line._prepare_invoice_line(qty=qty)
                vals.update({'invoice_id': invoice_id, 'sale_line_ids': [(6, 0, [line.id])]})
                self.env['account.invoice.line'].create(vals)

    @api.multi
    @api.onchange('product_id')
    def product_id_change(self):
        if not self.product_id:
            return {'domain': {'product_uom': []}}

        vals = {}
        domain = {'product_uom': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
        if not (self.product_uom and (self.product_id.uom_id.category_id.id == self.product_uom.category_id.id)):
            vals['product_uom'] = self.product_id.uom_id

        product = self.product_id.with_context(
            lang=self.order_id.partner_id.lang,
            partner=self.order_id.partner_id.id,
            quantity=self.product_uom_qty,
            date=self.order_id.date_order,
            pricelist=self.order_id.pricelist_id.id,
            uom=self.product_uom.id
        )

        name = product.name_get()[0][1]
        if product.description_sale:
            name += '\n' + product.description_sale
        vals['name'] = name

        if self.order_id.pricelist_id and self.order_id.partner_id:
            vals['price_unit'] = product.price
        self.update(vals)
        return {'domain': domain}

    @api.onchange('product_uom')
    def product_uom_change(self):
        if not self.product_uom:
            self.price_unit = 0.0
            return
        if self.order_id.pricelist_id and self.order_id.partner_id:
            product = self.product_id.with_context(
                lang=self.order_id.partner_id.lang,
                partner=self.order_id.partner_id.id,
                quantity=self.product_uom_qty,
                date_order=self.order_id.date_order,
                pricelist=self.order_id.pricelist_id.id,
                uom=self.product_uom.id
            )
            self.price_unit = product.price

    @api.multi
    def unlink(self):
        if self.filtered(lambda x: x.state in ('sale', 'done')):
            raise UserError(_('You can not remove a sale order line.\nDiscard changes and try setting the quantity to 0.'))
        return super(SaleOrderLine, self).unlink()

    @api.multi
    def _get_delivered_qty(self):
        '''
        Intended to be overridden in sale_stock and sale_mrp
        :return: the quantity delivered
        :rtype: float
        '''
        return 0.0
示例#14
0
文件: sale.py 项目: nitinitprof/odoo
class SaleOrder(models.Model):
    _name = "sale.order"
    _inherit = ['mail.thread', 'ir.needaction_mixin']
    _description = "Sales Order"
    _order = 'date_order desc, id desc'

    @api.depends('order_line.product_uom_qty', 'order_line.discount', 'order_line.price_unit', 'order_line.tax_id')
    def _amount_all(self):
        amount_untaxed = amount_tax = 0.0
        for line in self.order_line:
            amount_untaxed += line.price_subtotal
            amount_tax += line.price_tax
        self.update({
            'amount_untaxed': self.pricelist_id.currency_id.round(amount_untaxed),
            'amount_tax': self.pricelist_id.currency_id.round(amount_tax),
            'amount_total': amount_untaxed + amount_tax,
        })

    @api.depends('state', 'order_line.invoice_status')
    def _get_invoiced(self):
        for order in self:
            invoice_ids = order.order_line.mapped('invoice_lines').mapped('invoice_id').ids

            if order.state not in ('sale', 'done'):
                invoice_status = 'no'
            elif any(line.invoice_status == 'to invoice' for line in order.order_line):
                invoice_status = 'to invoice'
            elif all(line.invoice_status == 'invoiced' for line in order.order_line):
                invoice_status = 'invoiced'
            elif all(line.invoice_status in ['invoiced', 'upselling'] for line in order.order_line):
                invoice_status = 'upselling'
            else:
                invoice_status = 'no'

            order.update({
                'invoice_count': len(set(invoice_ids)),
                'invoice_ids': invoice_ids,
                'invoice_status': invoice_status
            })

    @api.model
    def _default_note(self):
        return self.env.user.company_id.sale_note

    @api.model
    def _get_default_team(self):
        default_team_id = self.env['crm.team']._get_default_team_id()
        return self.env['crm.team'].browse(default_team_id)

    @api.onchange('fiscal_position_id')
    def _compute_tax_id(self):
        for order in self:
            order.order_line._compute_tax_id()

    name = fields.Char(string='Order Reference', required=True, copy=False, readonly=True, index=True, default='New')
    origin = fields.Char(string='Source Document', help="Reference of the document that generated this sales order request.")
    client_order_ref = fields.Char(string='Customer Reference', copy=False)

    state = fields.Selection([
        ('draft', 'Quotation'),
        ('sent', 'Quotation Sent'),
        ('sale', 'Sale Order'),
        ('done', 'Done'),
        ('cancel', 'Cancelled'),
        ], string='Status', readonly=True, copy=False, index=True, default='draft')
    date_order = fields.Datetime(string='Order Date', required=True, readonly=True, index=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, copy=False, default=fields.Date.context_today)
    validity_date = fields.Date(string='Expiration Date', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]})
    create_date = fields.Datetime(string='Creation Date', readonly=True, index=True, help="Date on which sales order is created.")

    user_id = fields.Many2one('res.users', string='Salesperson', index=True, track_visibility='onchange', default=lambda self: self.env.user)
    partner_id = fields.Many2one('res.partner', string='Customer', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, required=True, change_default=True, index=True, track_visibility='always')
    partner_invoice_id = fields.Many2one('res.partner', string='Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Invoice address for current sales order.")
    partner_shipping_id = fields.Many2one('res.partner', string='Delivery Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Delivery address for current sales order.")

    pricelist_id = fields.Many2one('product.pricelist', string='Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order.")
    currency_id = fields.Many2one("res.currency", related='pricelist_id.currency_id', string="Currency", readonly=True, required=True)
    project_id = fields.Many2one('account.analytic.account', 'Analytic Account', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order.", copy=False)

    order_line = fields.One2many('sale.order.line', 'order_id', string='Order Lines', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True)

    invoice_count = fields.Integer(string='# of Invoices', compute='_get_invoiced', store=True, readonly=True)
    invoice_ids = fields.Many2many("account.invoice", string='Invoices', compute="_get_invoiced", readonly=True, copy=False)
    invoice_status = fields.Selection([
        ('upselling', 'Upselling Opportunity'),
        ('invoiced', 'Fully Invoiced'),
        ('to invoice', 'To Invoice'),
        ('no', 'Nothing to Invoice')
        ], string='Invoice Status', compute='_get_invoiced', store=True, readonly=True, default='no')

    note = fields.Text('Terms and conditions', default=_default_note)

    amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all', track_visibility='always')
    amount_tax = fields.Monetary(string='Taxes', store=True, readonly=True, compute='_amount_all', track_visibility='always')
    amount_total = fields.Monetary(string='Total', store=True, readonly=True, compute='_amount_all', track_visibility='always')

    payment_term_id = fields.Many2one('account.payment.term', string='Payment Term', oldname='payment_term')
    fiscal_position_id = fields.Many2one('account.fiscal.position', oldname='fiscal_position', string='Fiscal Position')
    company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env['res.company']._company_default_get('sale.order'))
    team_id = fields.Many2one('crm.team', 'Sales Team', change_default=True, default=_get_default_team)
    procurement_group_id = fields.Many2one('procurement.group', 'Procurement Group', copy=False)

    product_id = fields.Many2one('product.product', related='order_line.product_id', string='Product')

    @api.multi
    def button_dummy(self):
        return True

    @api.multi
    def unlink(self):
        for order in self:
            if order.state != 'draft':
                raise UserError(_('You can only delete draft quotations!'))
        return super(SaleOrder, self).unlink()

    @api.multi
    def _track_subtype(self, init_values):
        self.ensure_one()
        if 'state' in init_values and self.state == 'sale':
            return 'sale.mt_order_confirmed'
        elif 'state' in init_values and self.state == 'sent':
            return 'sale.mt_order_sent'
        return super(SaleOrder, self)._track_subtype(init_values)


    @api.onchange('partner_shipping_id')
    def onchange_partner_shipping_id(self):
        fiscal_position = self.env['account.fiscal.position'].get_fiscal_position(self.partner_id.id, self.partner_shipping_id.id)
        if fiscal_position:
            self.fiscal_position_id = fiscal_position
        return {}

    @api.multi
    @api.onchange('partner_id')
    def onchange_partner_id(self):
        if not self.partner_id:
            self.update({
                'partner_invoice_id': False,
                'partner_shipping_id': False,
                'payment_term_id': False,
                'fiscal_position_id': False,
            })
            return

        addr = self.partner_id.address_get(['delivery', 'invoice'])
        values = {
            'pricelist_id': self.partner_id.property_product_pricelist and self.partner_id.property_product_pricelist.id or False,
            'payment_term_id': self.partner_id.property_payment_term_id and self.partner_id.property_payment_term_id.id or False,
            'partner_invoice_id': addr['invoice'],
            'partner_shipping_id': addr['delivery'],
        }

        if self.partner_id.user_id:
            values['user_id'] = self.partner_id.user_id.id
        if self.partner_id.team_id:
            values['team_id'] = self.partner_id.team_id.id
        self.update(values)

    @api.model
    def create(self, vals):
        if vals.get('name', 'New') == 'New':
            vals['name'] = self.env['ir.sequence'].next_by_code('sale.order') or 'New'
        if any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id']):
            partner = self.env['res.partner'].browse(vals.get('partner_id'))
            addr = partner.address_get(['delivery', 'invoice'])
            vals['partner_invoice_id'] = vals.setdefault('partner_invoice_id', addr['invoice'])
            vals['partner_shipping_id'] = vals.setdefault('partner_shipping_id', addr['delivery'])
            vals['pricelist_id'] = vals.setdefault('pricelist_id', partner.property_product_pricelist and partner.property_product_pricelist.id)
        result = super(SaleOrder, self).create(vals)
        self.message_post(body=_("Quotation created"))
        return result

    @api.multi
    def _prepare_invoice(self):
        """Prepare the dict of values to create the new invoice for a
           sales order. This method may be overridden to implement custom
           invoice generation (making sure to call super() to establish
           a clean extension chain).
        """
        self.ensure_one()
        journal_ids = self.env['account.journal'].search([('type', '=', 'sale'), ('company_id', '=', self.company_id.id)], limit=1)
        if not journal_ids:
            raise UserError(_('Please define an accounting sale journal for this company.'))
        invoice_vals = {
            'name': self.client_order_ref or '',
            'origin': self.name,
            'type': 'out_invoice',
            'reference': self.client_order_ref or self.name,
            'account_id': self.partner_invoice_id.property_account_receivable_id.id,
            'partner_id': self.partner_invoice_id.id,
            'journal_id': journal_ids[0].id,
            'currency_id': self.pricelist_id.currency_id.id,
            'comment': self.note,
            'payment_term_id': self.payment_term_id.id,
            'fiscal_position_id': self.fiscal_position_id.id or self.partner_invoice_id.property_account_position_id.id,
            'company_id': self.company_id.id,
            'user_id': self.user_id and self.user_id.id,
            'team_id': self.team_id.id
        }
        return invoice_vals

    @api.multi
    def print_quotation(self):
        self.filtered(lambda s: s.state == 'draft').write({'state': 'sent'})
        return self.env['report'].get_action(self, 'sale.report_saleorder')

    @api.multi
    def action_view_invoice(self):
        self.ensure_one()
        imd = self.env['ir.model.data']
        action = imd.xmlid_to_object('account.action_invoice_tree1')
        list_view_id = imd.xmlid_to_res_id('account.invoice_tree')
        form_view_id = imd.xmlid_to_res_id('account.invoice_form')

        result = {
            'name': action.name,
            'help': action.help,
            'type': action.type,
            'views': [[list_view_id, 'tree'], [form_view_id, 'form'], [False, 'graph'], [False, 'kanban'], [False, 'calendar'], [False, 'pivot']],
            'target': action.target,
            'context': action.context,
            'res_model': action.res_model,
        }
        if len(self.invoice_ids) > 1:
            result['domain'] = "[('id','in',%s)]" % self.invoice_ids.ids
        elif len(self.invoice_ids) == 1:
            result['views'] = [(form_view_id, 'form')]
            result['res_id'] = self.invoice_ids.id
        else:
            result = {'type': 'ir.actions.act_window_close'}
        return result

    @api.multi
    def action_invoice_create(self, grouped=False, final=False):
        inv_obj = self.env['account.invoice']
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        invoices = {}

        for order in self:
            group_key = order.id if grouped else (order.partner_id.id, order.currency_id.id)
            for line in order.order_line.sorted(key=lambda l: l.qty_to_invoice < 0):
                if float_is_zero(line.qty_to_invoice, precision_digits=precision):
                    continue
                if group_key not in invoices:
                    inv_data = order._prepare_invoice()
                    invoice = inv_obj.create(inv_data)
                    invoices[group_key] = invoice
                if line.qty_to_invoice > 0:
                    line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice)
                elif line.qty_to_invoice < 0 and (final or invoices[group_key].amount_untaxed > abs(line.qty_to_invoice * line.price_unit)):
                    line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice)

        for invoice in invoices.values():
            # If invoice is negative, do a refund invoice instead
            if invoice.amount_untaxed < 0:
                invoice.type = 'out_refund'
                for line in invoice.invoice_line_ids:
                    line.quantity = -line.quantity
            # Necessary to force computation of taxes. In account_invoice, they are triggered
            # by onchanges, which are not triggered when doing a create.
            invoice.compute_taxes()

        return [inv.id for inv in invoices.values()]

    @api.multi
    def action_draft(self):
        self.filtered(lambda s: s.state in ['cancel', 'sent']).write({'state': 'draft'})

    @api.multi
    def action_cancel(self):
        self.write({'state': 'cancel'})

    @api.multi
    def action_quotation_send(self):
        '''
        This function opens a window to compose an email, with the edi sale template message loaded by default
        '''
        self.ensure_one()
        ir_model_data = self.env['ir.model.data']
        try:
            template_id = ir_model_data.get_object_reference('sale', 'email_template_edi_sale')[1]
        except ValueError:
            template_id = False
        try:
            compose_form_id = ir_model_data.get_object_reference('mail', 'email_compose_message_wizard_form')[1]
        except ValueError:
            compose_form_id = False
        ctx = dict()
        ctx.update({
            'default_model': 'sale.order',
            'default_res_id': self.ids[0],
            'default_use_template': bool(template_id),
            'default_template_id': template_id,
            'default_composition_mode': 'comment',
            'mark_so_as_sent': True
        })
        return {
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'mail.compose.message',
            'views': [(compose_form_id, 'form')],
            'view_id': compose_form_id,
            'target': 'new',
            'context': ctx,
        }

    @api.multi
    def force_quotation_send(self):
        for order in self:
            email_act = order.action_quotation_send()
            if email_act and email_act.get('context'):
                email_ctx = email_act['context']
                email_ctx.update(default_email_from=order.company_id.email)
                order.with_context(email_ctx).message_post_with_template(email_ctx.get('default_template_id'))
        return True

    @api.multi
    def action_done(self):
        self.write({'state': 'done'})

    @api.model
    def _prepare_procurement_group(self):
        return {'name': self.name}

    @api.multi
    def action_confirm(self):
        for order in self:
            order.state = 'sale'
            order.order_line._action_procurement_create()
            if not order.project_id:
                for line in order.order_line:
                    if line.product_id.invoice_policy == 'cost':
                        order._create_analytic_account()
                        break

    @api.multi
    def _create_analytic_account(self, prefix=None):
        for order in self:
            name = order.name
            if prefix:
                name = prefix + ": " + order.name
            analytic = self.env['account.analytic.account'].create({
                'name': name,
                'code': order.client_order_ref,
                'company_id': order.company_id.id,
                'partner_id': order.partner_id.id
            })
            order.project_id = analytic
示例#15
0
class Encounter(models.Model):
    _name = "hc.res.encounter"
    _description = "Encounter"

    identifier_ids = fields.One2many(
        comodel_name="hc.encounter.identifier",
        inverse_name="encounter_id",
        string="Identifiers",
        help="Identifier(s) by which this encounter is known.")
    status = fields.Selection(string="Encounter Status",
                              required="True",
                              selection=[("planned", "Planned"),
                                         ("arrived", "Arrived"),
                                         ("in-progress", "In-Progress"),
                                         ("onleave", "On Leave"),
                                         ("finished", "Finished"),
                                         ("cancelled", "Cancelled")],
                              help="Current state of the encounter.")
    encounter_class = fields.Selection(string="Encounter Class",
                                       selection=[("inpatient", "Inpatient"),
                                                  ("outpatient", "Outpatient"),
                                                  ("ambulatory", "Ambulatory"),
                                                  ("emergency", "Emergency")],
                                       help="Classification of the encounter.")
    type_ids = fields.Many2many(comodel_name="hc.vs.encounter.type",
                                string="Types",
                                help="Specific type of encounter.")
    priority_id = fields.Many2one(
        comodel_name="hc.vs.act.priority",
        string="Priority",
        help="Indicates the urgency of the encounter.")
    patient_id = fields.Many2one(comodel_name="hc.res.patient",
                                 string="Patient",
                                 help="The patient present at the encounter.")
    episode_of_care_ids = fields.One2many(
        comodel_name="hc.encounter.episode.of.care",
        inverse_name="encounter_id",
        string="Episodes of Care",
        help=
        "Episode(s) of care that this encounter should be recorded against.")
    incoming_referral_ids = fields.One2many(
        comodel_name="hc.encounter.referral.request",
        inverse_name="encounter_id",
        string="Incoming Referrals",
        help="The ReferralRequest that initiated this encounter.")
    # appointment_id = fields.Many2one(
    #     comodel_name="hc.res.appointment",
    #     string="Appointment",
    #     help="The appointment that scheduled this encounter.")
    start_date = fields.Datetime(string="Start Date",
                                 help="Start of the encounter.")
    end_date = fields.Datetime(string="End Date", help="End of the encounter.")
    length_uom_id = fields.Many2one(
        comodel_name="hc.vs.uom",
        string="Length UOM",
        help=
        "Quantity of time the encounter lasted (less time absent) unit of measure."
    )
    length = fields.Float(
        string="Length",
        help="Quantity of time the encounter lasted (less time absent).")
    reason_ids = fields.Many2many(
        comodel_name="hc.vs.encounter.reason",
        string="Reasons",
        help="Reason the encounter takes place (code).")
    indication_ids = fields.One2many(
        comodel_name="hc.encounter.indication",
        inverse_name="encounter_id",
        string="Indications",
        help="Reason the encounter takes place (resource).")
    account_ids = fields.One2many(
        comodel_name="hc.encounter.account",
        inverse_name="encounter_id",
        string="Accounts",
        help=
        "The set of accounts that may be used for billing for this Encounter.")
    service_provider_id = fields.Many2one(
        comodel_name="hc.res.organization",
        string="Service Provider",
        help="The custodian organization of this Encounter record.")
    part_of_id = fields.Many2one(
        comodel_name="hc.res.encounter",
        string="Part Of",
        help="Another Encounter this encounter is part of.")
    status_history_ids = fields.One2many(
        comodel_name="hc.encounter.status.history",
        inverse_name="encounter_id",
        string="Status History",
        help="List of Encounter statuses.")
    participant_ids = fields.One2many(
        comodel_name="hc.encounter.participant",
        inverse_name="encounter_id",
        string="Participants",
        help="List of participants involved in the encounter.")
    hospitalization_ids = fields.One2many(
        comodel_name="hc.encounter.hospitalization",
        inverse_name="encounter_id",
        string="Hospitalizations",
        help="Details about an admission to a clinic.")
    location_ids = fields.One2many(
        comodel_name="hc.encounter.location",
        inverse_name="encounter_id",
        string="Locations",
        help="List of locations the patient has been at.")
class FinancieraSmsMessageMasive(models.Model):
    _name = 'financiera.sms.message.masive'

    _order = 'id desc'
    name = fields.Char("Nombre")
    partner_ids = fields.Many2many('res.partner',
                                   'financiera_partner_messagemasive_rel',
                                   'partner_id',
                                   'masivemessage_id',
                                   string='Destinatarios')
    template_id = fields.Many2one('financiera.sms.message.masive.template',
                                  'Plantilla')
    tipo = fields.Char('Tipo de mensaje')
    body_count_available = fields.Integer(
        'Caracteres restantes', compute='_compute_body_count_available')
    body = fields.Text('Mensaje', size=160)
    is_html = fields.Boolean('Adjuntar html')
    html = fields.Text('Html')
    company_id = fields.Many2one('res.company', 'Empresa')
    message_ids = fields.One2many('financiera.sms.message',
                                  'sms_message_masive_id', 'Mensajes')
    state = fields.Selection([('draft', 'Borrador'), ('send', 'Enviado')],
                             string='Estado',
                             readonly=True,
                             default='draft')

    @api.model
    def create(self, values):
        rec = super(FinancieraSmsMessageMasive, self).create(values)
        sms_masivo_count = rec.company_id.sms_configuracion_id.sms_message_masive_count
        rec.update({
            'name': 'SMS MASIVO/' + str(sms_masivo_count).zfill(6),
        })
        rec.company_id.sms_configuracion_id.sms_message_masive_count = sms_masivo_count + 1
        return rec

    @api.model
    def default_get(self, fields):
        rec = super(FinancieraSmsMessageMasive, self).default_get(fields)
        # configuracion_id = self.env.user.company_id.configuracion_id
        context = dict(self._context or {})
        current_uid = context.get('uid')
        current_user = self.env['res.users'].browse(current_uid)
        company_id = current_user.company_id
        rec.update({
            'company_id': company_id.id,
        })
        return rec

    @api.onchange('body', 'is_html')
    def _compute_body_count_available(self):
        if self.body:
            if not self.is_html:
                self.body_count_available = 160 - len(self.body)
            else:
                self.body_count_available = 137 - len(self.body)
        else:
            if not self.is_html:
                self.body_count_available = 160
            else:
                self.body_count_available = 137

    @api.constrains('body', 'is_html')
    def _check_body(self):
        if self.body:
            if self.body_count_available < 0:
                raise UserError("Debe borrar al menos %s caracteres." %
                                str(abs(self.body_count_available)))

    @api.onchange('template_id')
    def _onchange_template_id(self):
        if self.template_id.tipo:
            self.tipo = self.template_id.tipo
        if self.template_id.body:
            self.body = self.template_id.body

    @api.one
    def partners_deseleccionar(self):
        self.partner_ids = [(6, 0, [])]

    # @api.one
    # def partners_cuota_preventiva(self):
    # 	cr = self.env.cr
    # 	uid = self.env.uid
    # 	cuota_obj = self.pool.get('financiera.prestamo.cuota')
    # 	cuota_ids = cuota_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('state_mora', '=', 'preventiva'),
    # 		('state', '=', 'activa')])
    # 	partner_obj = self.pool.get('res.partner')
    # 	partner_ids = partner_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('cuota_ids.id', 'in', cuota_ids)])
    # 	self.partner_ids = [(6, 0, partner_ids)]

    # @api.one
    # def partners_cuota_vencida(self):
    # 	cr = self.env.cr
    # 	uid = self.env.uid
    # 	fecha_actual = datetime.now()
    # 	cuota_obj = self.pool.get('financiera.prestamo.cuota')
    # 	cuota_ids = cuota_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('fecha_vencimiento', '<', fecha_actual),
    # 		('state', '=', 'activa')])
    # 	partner_obj = self.pool.get('res.partner')
    # 	partner_ids = partner_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('cuota_ids.id', 'in', cuota_ids)])
    # 	self.partner_ids = [(6, 0, partner_ids)]

    # @api.one
    # def partners_cuota_vencida_moraTemprana(self):
    # 	cr = self.env.cr
    # 	uid = self.env.uid
    # 	fecha_actual = datetime.now()
    # 	cuota_obj = self.pool.get('financiera.prestamo.cuota')
    # 	cuota_ids = cuota_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('fecha_vencimiento', '<', fecha_actual),
    # 		('state', '=', 'activa'),
    # 		('state_mora', '=', 'moraTemprana')])
    # 	partner_obj = self.pool.get('res.partner')
    # 	partner_ids = partner_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('cuota_ids.id', 'in', cuota_ids)])
    # 	self.partner_ids = [(6, 0, partner_ids)]
    # @api.one
    # def partners_cuota_vencida_moraMedia(self):
    # 	cr = self.env.cr
    # 	uid = self.env.uid
    # 	fecha_actual = datetime.now()
    # 	cuota_obj = self.pool.get('financiera.prestamo.cuota')
    # 	cuota_ids = cuota_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('fecha_vencimiento', '<', fecha_actual),
    # 		('state', '=', 'activa'),
    # 		('state_mora', '=', 'moraMedia')])
    # 	partner_obj = self.pool.get('res.partner')
    # 	partner_ids = partner_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('cuota_ids.id', 'in', cuota_ids)])
    # 	self.partner_ids = [(6, 0, partner_ids)]

    # @api.one
    # def partners_cuota_vencida_moraTardia(self):
    # 	cr = self.env.cr
    # 	uid = self.env.uid
    # 	fecha_actual = datetime.now()
    # 	cuota_obj = self.pool.get('financiera.prestamo.cuota')
    # 	cuota_ids = cuota_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('fecha_vencimiento', '<', fecha_actual),
    # 		('state', '=', 'activa'),
    # 		('state_mora', '=', 'moraTardia')])
    # 	partner_obj = self.pool.get('res.partner')
    # 	partner_ids = partner_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('cuota_ids.id', 'in', cuota_ids)])
    # 	self.partner_ids = [(6, 0, partner_ids)]

    # @api.one
    # def partners_cuota_vencida_incobrable(self):
    # 	cr = self.env.cr
    # 	uid = self.env.uid
    # 	fecha_actual = datetime.now()
    # 	cuota_obj = self.pool.get('financiera.prestamo.cuota')
    # 	cuota_ids = cuota_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('fecha_vencimiento', '<', fecha_actual),
    # 		('state', '=', 'activa'),
    # 		('state_mora', '=', 'incobrable')])
    # 	partner_obj = self.pool.get('res.partner')
    # 	partner_ids = partner_obj.search(cr, uid, [
    # 		('company_id', '=', self.company_id.id),
    # 		('cuota_ids.id', 'in', cuota_ids)])
    # 	self.partner_ids = [(6, 0, partner_ids)]

    @api.one
    def send_messages(self):
        if len(self.partner_ids) > 0:
            config_id = self.company_id.sms_configuracion_id
            for partner_id in self.partner_ids:
                sms_message_values = {
                    'partner_id': partner_id.id,
                    'config_id': config_id.id,
                    'to': partner_id.mobile,
                    'tipo': self.tipo or 'Personalizado',
                    'company_id': self.company_id.id,
                }
                message_id = self.env['financiera.sms.message'].create(
                    sms_message_values)
                message_id.body = self.body
                if self.is_html:
                    message_id.html = self.html
                message_id.send()
                self.message_ids = [message_id.id]
            self.state = 'send'
        else:
            raise UserError("Debe agregar al menos un destinatario.")
class HrExpenseExpense(models.Model):
    _inherit = 'hr.expense.expense'

    level_id = fields.Many2one(
        'level.validation',
        string='Validation Level',
        track_visibility='onchange',
        copy=False,
    )
    approver_ids = fields.Many2many(
        'res.users',
        'hr_approver_rel',
        'expense_id', 'user_id',
        string='Approver',
        track_visibility='onchange',
        copy=False,
    )
    approve_permission = fields.Boolean(
        string='Approve Permission',
        compute='_compute_approve_permission',
    )
    state = fields.Selection(
        selection=[
            ('draft', 'New'),
            ('cancelled', 'Refused'),
            ('confirm', 'Waiting Approval'),
            ('validate', 'Waiting Validate'),
            ('accepted', 'Approved'),
            ('done', 'Waiting Payment'),
            ('paid', 'Paid'),
        ],
    )

    @api.multi
    def action_check_approval(self):
        self.ensure_one()
        amount = self.amount
        doctype = ''
        if self.is_employee_advance:
            doctype = 'employee_advance'
        elif self.is_advance_clearing:
            doctype = 'employee_clearing'
        elif self.pay_to == 'pettycash':
            doctype = 'employee_pettycash'
        elif not self.is_advance_clearing and not self.is_employee_advance:
            doctype = 'employee_expense'

        levels = self.env['level.validation'].search([
            ('operating_unit_id', '=', self.operating_unit_id.id),
            ('doctype', 'like', doctype),
        ]).sorted(key=lambda r: r.level)

        if not levels:
            raise ValidationError(_("This operating unit does not "
                                    "set approver."))
        levels_lt_amount = levels.filtered(
            lambda r: r.limit_amount < amount)
        levels_gt_amount = levels.filtered(
            lambda r: r.limit_amount >= amount)

        if levels_gt_amount:
            target_levels = levels_lt_amount + levels.filtered(
                lambda r: r.level == min(levels_gt_amount.mapped('level')))
        else:
            target_levels = levels_lt_amount
            if not target_levels.filtered(
                    lambda r: r.limit_amount >= amount):
                raise ValidationError(_("Amount is over "
                                        "maximum limited amount."))

        if self.approver_ids and self.env.user not in self.approver_ids:
            raise ValidationError(_("Your user is not allow to "
                                    "approve this document."))
        if target_levels:
            if self.level_id:
                min_level = min(filter(lambda r: r >= self.level_id.level,
                                       target_levels.mapped('level')))
                target_level = target_levels.filtered(
                    lambda r: r.level == min_level + 1)
                if target_level:
                    self.write({
                        'level_id': target_level.id,
                        'approver_ids': [
                            (6, 0, target_level.user_ids.ids)
                        ],
                    })
                else:
                    self.write({
                        'level_id': False,
                        'approver_ids': False,
                    })
            else:
                if not self.level_id and not self.approver_ids:
                    target_level = target_levels.filtered(
                        lambda r: r.level == min(target_levels.mapped('level'))
                    )
                    self.write({
                        'level_id': target_level.id,
                        'approver_ids': [
                            (6, 0, target_level.user_ids.ids)
                        ],
                    })
        return True

    @api.depends('approver_ids')
    def _compute_approve_permission(self):
        for order in self:
            order.approve_permission = \
                bool(self.env.user in order.approver_ids)

    @api.multi
    def action_validated(self):
        self.ensure_one()
        return self.write({'state': 'validate'})

    @api.multi
    def expense_accept(self):
        self.ensure_one()
        res = super(HrExpenseExpense, self).expense_accept()
        product_lines = self.env['hr.expense.line'].search([
            ('expense_id', '=', self.id)
        ]).mapped('product_id')
        hr_categories = self.env['product.category'].search([('hr_product',
                                                              '=', True)])
        hr_products = product_lines.filtered(
            lambda r: r.categ_id in hr_categories
        )
        group_hr = self.env.ref('hr.group_validate_hr_product')
        if hr_products and self.env.user not in group_hr.users:
            raise ValidationError(
                _("You are not allowed to validate document with HR Product."))
        return res
示例#18
0
class IrUiMenu(models.Model):
    _name = 'builder.ir.ui.menu'

    _rec_name = 'complete_name'

    @api.multi
    def get_user_roots(self):
        """ Return all root menu ids visible for the user.

        :return: the root menu ids
        :rtype: list(int)
        """
        menu_domain = [('parent_id', '=', False), ('parent_ref', '=', False)]
        return self.search(menu_domain)

    @api.multi
    def load_menus_root(self):
        menu_roots = self.get_user_roots()
        return {
            'id': False,
            'name': 'root',
            'parent_id': [-1, ''],
            'children': menu_roots,
            'all_menu_ids': [i.id for i in menu_roots],
        }

    def _get_full_name(self, cr, uid, ids, name=None, args=None, context=None):
        if context is None:
            context = {}
        res = {}
        for elmt in self.browse(cr, uid, ids, context=context):
            res[elmt.id] = self._get_one_full_name(elmt)
        return res

    def _get_one_full_name(self, elmt, level=6):
        if level <= 0:
            return '...'
        if elmt.parent_id:
            parent_path = self._get_one_full_name(
                elmt.parent_id, level - 1) + MENU_ITEM_SEPARATOR
        else:
            parent_path = ''
        return parent_path + elmt.name

    @api.onchange('parent_ref')
    def onchange_parent_ref(self):
        self.parent_menu_id = False
        if self.parent_ref:
            self.parent_menu_id = self.env['ir.model.data'].xmlid_to_res_id(
                self.parent_ref)

    @api.onchange('parent_menu_id')
    def onchange_parent_menu_id(self):
        if self.parent_menu_id:
            data = self.env['ir.model.data'].search([
                ('model', '=', 'ir.ui.menu'),
                ('res_id', '=', self.parent_menu_id.id)
            ])
            self.parent_ref = "{module}.{id}".format(
                module=data.module, id=data.name) if data.id else False

    @api.onchange('parent_type')
    def onchange_parent_type(self):
        self.parent_ref = False
        self.parent_menu_id = False
        self.parent_id = False

    module_id = fields.Many2one('builder.ir.module.module',
                                'Module',
                                ondelete='cascade')
    name = fields.Char('Menu', required=True, translate=True)
    xml_id = fields.Char('XML ID', required=True)
    complete_name = fields.Char('Complete Name',
                                compute='_compute_complete_name')
    morder = fields.Integer('Order')
    sequence = fields.Integer('Sequence')
    child_ids = fields.One2many('builder.ir.ui.menu',
                                'parent_id',
                                'Child Ids',
                                copy=True)
    # group_ids = fields.Many2many('builder.res.groups', 'builder_ir_ui_menu_group_rel', 'menu_id', 'gid', 'Groups', help="If you have groups, the visibility of this menu will be based on these groups. "\
    #             "If this field is empty, Odoo will compute visibility based on the related object's read access.")
    parent_menu_id = fields.Many2one('ir.ui.menu',
                                     'System Menu',
                                     ondelete='set null')
    parent_ref = fields.Char('System Menu Ref', select=True)
    parent_id = fields.Many2one('builder.ir.ui.menu',
                                'Parent Menu',
                                select=True,
                                ondelete='cascade')
    parent_type = fields.Selection([('module', 'Module'),
                                    ('system', 'System')], 'Parent Type')
    parent_left = fields.Integer('Parent Left', select=True)
    parent_right = fields.Integer('Parent Left', select=True)
    action_type = fields.Selection([('module', 'Module'),
                                    ('system', 'System')], 'Action Type')
    action_system_ref = fields.Char('Action System Ref')
    action_system = fields.Reference([
        ('ir.actions.report.xml', 'ir.actions.report.xml'),
        ('ir.actions.act_window', 'ir.actions.act_window'),
        ('ir.actions.wizard', 'ir.actions.wizard'),
        ('ir.actions.act_url', 'ir.actions.act_url'),
        ('ir.actions.server', 'ir.actions.server'),
        ('ir.actions.client', 'ir.actions.client'),
    ], 'System Action')

    action_module = fields.Reference(
        [
            ('builder.ir.actions.act_window', 'Window'),
            # ('builder.ir.actions.act_url', 'URL'),
        ],
        'Module Action')

    group_ids = fields.Many2many(
        'builder.res.groups',
        'builder_ir_ui_menu_group_rel',
        'menu_id',
        'gid',
        string='Groups',
        help=
        "If this field is empty, the menu applies to all users. Otherwise, the view applies to the users of those groups only."
    )

    @api.onchange('action_system')
    def onchange_action_system(self):
        if self.action_system:
            model, res_id = self.action_system._name, self.action_system.id
            data = self.env['ir.model.data'].search([('model', '=', model),
                                                     ('res_id', '=', res_id)])
            self.action_system_ref = "{module}.{id}".format(
                module=data.module, id=data.name) if data.id else False

            self.name = self.action_system.name
            self.xml_id = "menu_{action}".format(
                action=self.action_system_ref.replace('.', '_'))

    @api.onchange('action_module')
    def onchange_action_module(self):
        if self.action_module:
            self.name = self.action_module.name
            self.xml_id = "menu_{action}".format(
                action=self.action_module.xml_id)

    @api.model
    @api.returns('self', lambda value: value.id)
    def create(self, vals):
        if not vals.get('parent_type', False):
            vals['parent_id'] = False
            vals['parent_menu_id'] = False
            vals['parent_ref'] = False

        return super(IrUiMenu, self).create(vals)

    @api.multi
    def write(self, vals):
        if not vals.get('parent_type', self.parent_type):
            vals['parent_id'] = False
            vals['parent_menu_id'] = False
            vals['parent_ref'] = False

        return super(IrUiMenu, self).write(vals)

    @api.one
    def _compute_complete_name(self):
        self.complete_name = self._get_full_name_one()

    @api.multi
    def _get_full_name_one(self, level=6):
        if level <= 0:
            return '...'
        parent_path = ''
        if self.parent_id:
            parent_path = self.parent_id._get_full_name_one(
                level - 1) + MENU_ITEM_SEPARATOR
        elif self.parent_ref:
            parent_path = _('[INHERITED]') + MENU_ITEM_SEPARATOR
            if self.parent_menu_id:
                parent_path = '[{name}]'.format(
                    name=self.parent_menu_id.complete_name
                ) + MENU_ITEM_SEPARATOR
            else:
                parent_path = '[{ref}]'.format(
                    ref=self.parent_ref) + MENU_ITEM_SEPARATOR

        return parent_path + self.name

    @api.one
    def name_get(self):
        return self.id, self._get_full_name_one()

    def _rec_message(self, cr, uid, ids, context=None):
        return _('Error ! You can not create recursive Menu.')

    _constraints = [(osv.osv._check_recursion, _rec_message, ['parent_id'])]
    _defaults = {
        'sequence': 10,
    }
    _order = "morder,id"
    _parent_store = True
class CompassionChild(models.Model):
    """ A sponsored child """
    _name = 'compassion.child'
    _rec_name = 'local_id'
    _inherit = [
        'compassion.generic.child', 'mail.thread', 'translatable.model'
    ]
    _description = "Sponsored Child"

    ##########################################################################
    #                                 FIELDS                                 #
    ##########################################################################

    # General Information
    #####################
    local_id = fields.Char(track_visibility=True)
    code = fields.Char(help='Old child reference')
    compass_id = fields.Char('Compass ID', oldname='unique_id')
    estimated_birthdate = fields.Boolean(readonly=True)
    cognitive_age_group = fields.Selection([
        ('0-2', '0-2'),
        ('3-5', '3-5'),
        ('6-8', '6-8'),
        ('9-11', '9-11'),
        ('12-14', '12-14'),
        ('15-18', '15-18'),
        ('19+', '19+'),
    ],
                                           readonly=True)
    cdsp_type = fields.Selection([
        ('Home based', 'Home based'),
        ('Center based', 'Center based'),
    ],
                                 track_visibility='onchange',
                                 readonly=True)
    last_review_date = fields.Date(track_visibility='onchange', readonly=True)
    type = fields.Selection([('CDSP', 'CDSP'), ('LDP', 'LDP')],
                            required=True,
                            default='CDSP')
    date = fields.Date('Allocation date')
    completion_date = fields.Date(readonly=True)
    completion_date_change_reason = fields.Char(readonly=True)
    state = fields.Selection('_get_child_states',
                             readonly=True,
                             required=True,
                             track_visibility='onchange',
                             default='N')
    is_available = fields.Boolean(compute='_set_available')
    sponsor_id = fields.Many2one('res.partner',
                                 'Sponsor',
                                 track_visibility='onchange',
                                 readonly=True)
    sponsor_ref = fields.Char('Sponsor reference', related='sponsor_id.ref')
    has_been_sponsored = fields.Boolean()
    hold_id = fields.Many2one('compassion.hold', 'Hold', readonly=True)
    active = fields.Boolean(default=True)
    exit_reason = fields.Char(compute='_compute_exit_reason')
    non_latin_name = fields.Char()
    # Beneficiary Favorites
    #######################
    hobby_ids = fields.Many2many('child.hobby',
                                 string='Hobbies',
                                 readonly=True)
    duty_ids = fields.Many2many('child.household.duty',
                                string='Household duties',
                                readonly=True)
    activity_ids = fields.Many2many('child.project.activity',
                                    string='Project activities',
                                    readonly=True)
    subject_ids = fields.Many2many('child.school.subject',
                                   string='School subjects',
                                   readonly=True)

    # Education information
    #######################
    education_level = fields.Selection([
        ('Not Enrolled', 'Not Enrolled'),
        ('Preschool', 'Preschool'),
        ('Primary', 'Primary'),
        ('Secondary', 'Secondary'),
        ('University Graduate', 'University Graduate'),
    ],
                                       readonly=True)
    local_grade_level = fields.Selection([
        ('Preschool 1', 'Preschool 1'),
        ('Preschool 2', 'Preschool 2'),
        ('Kinder 1', 'Kinder 1'),
        ('Kinder 2', 'Kinder 2'),
        ('Kinder 3', 'Kinder 3'),
        ('Primary 1', 'Primary 1'),
        ('Primary 2', 'Primary 2'),
        ('Primary 3', 'Primary 3'),
        ('Primary 4', 'Primary 4'),
        ('Primary 5', 'Primary 5'),
        ('Primary 6', 'Primary 6'),
        ('Middle 1', 'Middle 1'),
        ('Middle 2', 'Middle 2'),
        ('Middle 3', 'Middle 3'),
        ('High school 1', 'High school 1'),
        ('High school 2', 'High school 2'),
        ('High school 3', 'High school 3'),
        ('Not Enrolled', 'Not Enrolled'),
    ],
                                         readonly=True)
    us_grade_level = fields.Selection([
        ('P', 'P'),
        ('K', 'K'),
        ('1', '1'),
        ('2', '2'),
        ('3', '3'),
        ('4', '4'),
        ('5', '5'),
        ('6', '6'),
        ('7', '7'),
        ('8', '8'),
        ('9', '9'),
        ('10', '10'),
        ('11', '11'),
        ('12', '12'),
        ('13', '13'),
        ('14', '14'),
        ('PK', 'PK'),
    ],
                                      readonly=True)
    academic_performance = fields.Selection([
        ('Above Average', _('above average')),
        ('Average', _('average')),
        ('Below Average', _('below average')),
    ],
                                            readonly=True)
    vocational_training_type = fields.Selection([
        ('Agriculture', _('agriculture')),
        ('Automotive', _('automotive')),
        ('Business/Administrative', _('business administration')),
        ('Clothing Trades', _('clothing trades')),
        ('Computer Technology', _('computer technology')),
        ('Construction/ Tradesman', _('construction')),
        ('Cooking / Food Service', _('cooking and food service')),
        ('Cosmetology', _('cosmetology')),
        ('Electrical/ Electronics', _('electronics')),
        ('Graphic Arts', _('graphic arts')),
        ('Income-Generating Program at Project',
         'Income-Generating Program at Project'),
        ('Manufacturing/ Fabrication', 'Manufacturing/ Fabrication'),
        ('Medical/ Health Services', 'Medical/ Health Services'),
        ('Not Enrolled', 'Not Enrolled'),
        ('Other', 'Other'),
        ('Telecommunication', _('telecommunication')),
        ('Transportation', _('transportation')),
        ('Transportation/ Driver', _('driver')),
    ],
                                                readonly=True)
    university_year = fields.Selection([
        ('1', '1'),
        ('2', '2'),
        ('3', '3'),
        ('4', '4'),
        ('5', '5'),
        ('6', '6'),
        ('7', '7'),
    ],
                                       readonly=True)
    major_course_study = fields.Selection([
        ('Accounting', _('accounting')),
        ('Agriculture', _('agriculture')),
        ('Biology / Medicine', _('biology/medicine')),
        ('Business / Management / Commerce', _('business management')),
        ('Community Development', _('community development')),
        ('Computer Science / Information Technology', _('computer science')),
        ('Criminology / Law Enforcement', _('criminology')),
        ('Economics', _('economics')),
        ('Education', _('education')),
        ('Engineering', _('engineering')),
        ('English', _('english')),
        ('Graphic Arts / Fine Arts', _('graphic arts')),
        ('History', _('history')),
        ('Hospitality / Hotel Management',
         _('hospitality / hotel '
           'management')),
        ('Law', _('law')),
        ('Mathematics', _('mathematics')),
        ('Nursing', _('nursing')),
        ('Other', 'Other'),
        ('Psychology', _('Psychology')),
        ('Sales and Marketing', _('sales and marketing')),
        ('Science', _('science')),
        ('Sociology / Social Science', _('sociology')),
        ('Theology', _('theology')),
        ('Tourism', _('tourism')),
    ],
                                          readonly=True)
    not_enrolled_reason = fields.Char(readonly=True)

    # Spiritual information
    #######################
    christian_activity_ids = fields.Many2many('child.christian.activity',
                                              string='Christian activities',
                                              readonly=True)

    # Medical information
    #####################
    weight = fields.Char(readonly=True)
    height = fields.Char(readonly=True)
    physical_disability_ids = fields.Many2many('child.physical.disability',
                                               string='Physical disabilities',
                                               readonly=True)
    chronic_illness_ids = fields.Many2many('child.chronic.illness',
                                           string='Chronic illnesses',
                                           readonly=True)

    # Case Studies
    ##############
    lifecycle_ids = fields.One2many('compassion.child.ble',
                                    'child_id',
                                    'Lifecycle events',
                                    readonly=True)
    assessment_ids = fields.One2many('compassion.child.cdpr',
                                     'child_id',
                                     'Assessments',
                                     readonly=True)
    note_ids = fields.One2many('compassion.child.note',
                               'child_id',
                               'Notes',
                               readonly=True)
    revised_value_ids = fields.One2many('compassion.major.revision',
                                        'child_id',
                                        'Major revisions',
                                        readonly=True)
    pictures_ids = fields.One2many('compassion.child.pictures',
                                   'child_id',
                                   'Child pictures',
                                   track_visibility='onchange',
                                   readonly=True)
    household_id = fields.Many2one('compassion.household',
                                   'Household',
                                   readonly=True)
    portrait = fields.Binary(related='pictures_ids.headshot')
    fullshot = fields.Binary(related='pictures_ids.fullshot')
    child_disaster_impact_ids = fields.One2many('child.disaster.impact',
                                                'child_id',
                                                'Child Disaster Impact')

    # Descriptions
    ##############
    desc_en = fields.Text('English description', readonly=True)
    desc_fr = fields.Text('French description', readonly=True)
    desc_de = fields.Text('German description', readonly=True)
    desc_it = fields.Text('Italian description', readonly=True)

    _sql_constraints = [('compass_id', 'unique(compass_id)',
                         _('The child already exists in database.')),
                        ('global_id', 'unique(global_id)',
                         _('The child already exists in database.'))]

    ##########################################################################
    #                             FIELDS METHODS                             #
    ##########################################################################
    @api.one
    @api.depends('local_id')
    def _set_project(self):
        if self.local_id:
            project = self.env['compassion.project'].search(
                [('icp_id', '=', self.local_id[:5])], limit=1)
            if not project:
                project = self.env['compassion.project'].create({
                    'icp_id':
                    self.local_id[:5],
                    'name':
                    self.local_id[:5],
                })
            self.project_id = project.id

    def _get_child_states(self):
        return [
            ('N', _('Consigned')),
            ('I', _('On Internet')),
            ('P', _('Sponsored')),
            ('F', _('Departed')),
            ('R', _('Released')),
        ]

    def _set_available(self):
        for child in self:
            child.is_available = child.state in self._available_states()

    def _available_states(self):
        return ['N', 'I']

    def _compute_exit_reason(self):
        for child in self:
            exit_details = child.lifecycle_ids.with_context(
                lang='en_US').filtered(lambda l: l.type in
                                       ('Planned Exit', 'Unplanned Exit'))
            if exit_details:
                child.exit_reason = exit_details[0].request_reason

    ##########################################################################
    #                              ORM METHODS                               #
    ##########################################################################
    @api.model
    def create(self, vals):
        """
        If child with global_id already exists, update it instead of creating
        a new one.
        """
        global_id = vals.get('global_id')
        child = self.search([('global_id', '=', global_id)])
        if child:
            child.write(vals)
        else:
            child = super(CompassionChild, self).create(vals)
        return child

    ##########################################################################
    #                             PUBLIC METHODS                             #
    ##########################################################################
    def details_answer(self, vals):
        """ Called when receiving the answer of GetDetails message. """
        self.ensure_one()
        self.write(vals)
        self.generate_descriptions()
        return True

    @api.model
    def major_revision(self, commkit_data):
        """ Called when a MajorRevision Kit is received. """
        child_ids = list()
        child_mapping = CompassionChildMapping(self.env)
        for child_data in commkit_data.get('BeneficiaryMajorRevisionList',
                                           [commkit_data]):
            global_id = child_data.get('Beneficiary_GlobalID')
            child = self.search([('global_id', '=', global_id)])
            if child:
                child_ids.append(child.id)
                child._major_revision(
                    child_mapping.get_vals_from_connect(child_data))
        return child_ids

    ##########################################################################
    #                             VIEW CALLBACKS                             #
    ##########################################################################
    @api.multi
    def get_infos(self):
        """Get the most recent case study, basic informations, updates
           portrait picture and creates the project if it doesn't exist.
        """
        message_obj = self.env['gmc.message.pool']
        action_id = self.env.ref('child_compassion.beneficiaries_details').id

        message_vals = {
            'action_id': action_id,
            'object_id': self.id,
            'child_id': self.id,
        }
        message_obj.create(message_vals)
        return True

    @api.multi
    def update_child_pictures(self):
        res = True
        # Update child's pictures
        for child in self:
            res = child._get_last_pictures() and res
        return res

    @api.multi
    def generate_descriptions(self):
        self.ensure_one()
        self.desc_fr = ChildDescriptionFr.gen_fr_translation(
            self.with_context(lang='fr_CH'))
        self.desc_de = ChildDescriptionDe.gen_de_translation(
            self.with_context(lang='de_DE'))
        self.desc_it = ChildDescriptionIt.gen_it_translation(
            self.with_context(lang='it_IT'))

    # Lifecycle methods
    ###################
    def depart(self):
        self.signal_workflow('release')

    def reinstatement(self):
        """ Called by Lifecycle Event. Hold and state of Child is
        handled by the Reinstatement Hold Notification. """
        self.delete_workflow()
        self.create_workflow()

    ##########################################################################
    #                            WORKFLOW METHODS                            #
    ##########################################################################
    @api.multi
    def child_consigned(self):
        """Called on child allocation."""
        self.write({'state': 'N', 'sponsor_id': False})
        self.with_context(async_mode=True).get_infos()
        return True

    @api.multi
    def child_sponsored(self):
        return self.write({'state': 'P', 'has_been_sponsored': True})

    @api.multi
    def child_released(self):
        """ Is called when a child is released to the global childpool. """
        sponsored_children = self.filtered('has_been_sponsored')
        sponsored_children.write({'sponsor_id': False, 'state': 'R'})
        other_children = self - sponsored_children
        other_children._postpone_deletion()
        return True

    @api.multi
    def child_departed(self):
        """ Is called when a child is departed. """
        sponsored_children = self.filtered('has_been_sponsored')
        sponsored_children.write({'sponsor_id': False, 'state': 'F'})
        other_children = self - sponsored_children
        other_children._postpone_deletion()
        return True

    ##########################################################################
    #                             PRIVATE METHODS                            #
    ##########################################################################
    def _postpone_deletion(self):
        postpone = datetime.now() + timedelta(seconds=10)
        session = ConnectorSession.from_env(self.env)
        unlink_children_job.delay(session, self._name, self.ids, eta=postpone)

    def _get_last_pictures(self):
        self.ensure_one()
        pictures_obj = self.env['compassion.child.pictures']
        pictures = pictures_obj.create({'child_id': self.id})
        if pictures:
            # Add a note in child
            self.message_post("The picture has been updated.",
                              "Picture update", 'comment')

        return pictures

    def _major_revision(self, vals):
        """ Private method when a major revision is received for a child.
            :param vals: Record values received from connect
        """
        self.ensure_one()
        self.write(vals)
class ResPartnerRelation(models.Model):
    '''Model res.partner.relation is used to describe all links or relations
    between partners in the database.

    In many parts of the code we have to know whether the active partner is
    the left partner, or the right partner. If the active partner is the
    right partner we have to show the inverse name.

    Because the active partner is crucial for the working of partner
    relationships, we make sure on the res.partner model that the partner id
    is set in the context where needed.
    '''
    _name = 'res.partner.relation'
    _description = 'Partner relation'
    _order = 'active desc, date_start desc, date_end desc'

    def _search_any_partner_id(self, operator, value):
        return [
            '|',
            ('left_partner_id', operator, value),
            ('right_partner_id', operator, value),
        ]

    def _get_computed_fields(
            self, cr, uid, ids, field_names, arg, context=None):
        '''Return a dictionary of dictionaries, with for every partner for
        ids, the computed values.'''
        def get_values(self, dummy_field_names, dummy_arg, context=None):
            '''Get computed values for record'''
            values = {}
            on_right_partner = self._on_right_partner(self.right_partner_id.id)
            # type_selection_id
            values['type_selection_id'] = (
                ((self.type_id.id) * 10) + (on_right_partner and 1 or 0))
            # partner_id_display
            values['partner_id_display'] = (
                self.left_partner_id.id
                if on_right_partner
                else self.right_partner_id.id
            )
            return values

        return dict([
            (i.id, get_values(i, field_names, arg, context=context))
            for i in self.browse(cr, uid, ids, context=context)
        ])

    _columns = {
        'type_selection_id': osv.fields.function(
            _get_computed_fields,
            multi="computed_fields",
            fnct_inv=lambda *args: None,
            type='many2one', obj='res.partner.relation.type.selection',
            string='Type',
        ),
        'partner_id_display': osv.fields.function(
            _get_computed_fields,
            multi="computed_fields",
            fnct_inv=lambda *args: None,
            type='many2one', obj='res.partner',
            string='Partner'
        ),
    }

    allow_self = fields.Boolean(related='type_id.allow_self')
    left_contact_type = fields.Selection(
        lambda s: s.env['res.partner.relation.type']._get_partner_types(),
        'Left Partner Type',
        compute='_get_partner_type_any',
        store=True,
    )

    right_contact_type = fields.Selection(
        lambda s: s.env['res.partner.relation.type']._get_partner_types(),
        'Right Partner Type',
        compute='_get_partner_type_any',
        store=True,
    )

    any_partner_id = fields.Many2many(
        'res.partner',
        string='Partner',
        compute='_get_partner_type_any',
        search='_search_any_partner_id'
    )

    left_partner_id = fields.Many2one(
        'res.partner',
        string='Source Partner',
        required=True,
        auto_join=True,
        ondelete='cascade',
    )

    right_partner_id = fields.Many2one(
        'res.partner',
        string='Destination Partner',
        required=True,
        auto_join=True,
        ondelete='cascade',
    )

    type_id = fields.Many2one(
        'res.partner.relation.type',
        string='Type',
        required=True,
        auto_join=True,
    )

    date_start = fields.Date('Starting date')
    date_end = fields.Date('Ending date')
    active = fields.Boolean('Active', default=True)

    @api.one
    @api.depends('left_partner_id', 'right_partner_id')
    def _get_partner_type_any(self):
        self.left_contact_type = get_partner_type(self.left_partner_id)
        self.right_contact_type = get_partner_type(self.right_partner_id)

        self.any_partner_id = self.left_partner_id + self.right_partner_id

    def _on_right_partner(self, cr, uid, right_partner_id, context=None):
        '''Determine wether functions are called in a situation where the
        active partner is the right partner. Default False!
        '''
        if (context and 'active_ids' in context and
                right_partner_id in context.get('active_ids', [])):
            return True
        return False

    def _correct_vals(self, vals):
        """Fill type and left and right partner id, according to whether
        we have a normal relation type or an inverse relation type
        """
        vals = vals.copy()
        # If type_selection_id ends in 1, it is a reverse relation type
        if 'type_selection_id' in vals:
            prts_model = self.env['res.partner.relation.type.selection']
            type_selection_id = vals['type_selection_id']
            (type_id, is_reverse) = (
                prts_model.browse(type_selection_id).
                get_type_from_selection_id()
            )
            vals['type_id'] = type_id
            if self._context.get('active_id'):
                if is_reverse:
                    vals['right_partner_id'] = self._context['active_id']
                else:
                    vals['left_partner_id'] = self._context['active_id']
            if vals.get('partner_id_display'):
                if is_reverse:
                    vals['left_partner_id'] = vals['partner_id_display']
                else:
                    vals['right_partner_id'] = vals['partner_id_display']
            if vals.get('other_partner_id'):
                if is_reverse:
                    vals['left_partner_id'] = vals['other_partner_id']
                else:
                    vals['right_partner_id'] = vals['other_partner_id']
                del vals['other_partner_id']
            if vals.get('contact_type'):
                del vals['contact_type']
        return vals

    @api.multi
    def write(self, vals):
        """Override write to correct values, before being stored."""
        vals = self._correct_vals(vals)
        return super(ResPartnerRelation, self).write(vals)

    @api.model
    def create(self, vals):
        """Override create to correct values, before being stored."""
        vals = self._correct_vals(vals)
        return super(ResPartnerRelation, self).create(vals)

    def on_change_type_selection_id(
            self, cr, uid, dummy_ids, type_selection_id, context=None):
        '''Set domain on partner_id_display, when selection a relation type'''
        result = {
            'domain': {'partner_id_display': []},
            'value': {'type_id': False}
        }
        if not type_selection_id:
            return result
        prts_model = self.pool['res.partner.relation.type.selection']
        type_model = self.pool['res.partner.relation.type']
        (type_id, is_reverse) = (
            prts_model.get_type_from_selection_id(
                cr, uid, type_selection_id)
        )
        result['value']['type_id'] = type_id
        type_obj = type_model.browse(cr, uid, type_id, context=context)
        partner_domain = []
        check_contact_type = type_obj.contact_type_right
        check_partner_category = (
            type_obj.partner_category_right and
            type_obj.partner_category_right.id
        )
        if is_reverse:
            # partner_id_display is left partner
            check_contact_type = type_obj.contact_type_left
            check_partner_category = (
                type_obj.partner_category_left and
                type_obj.partner_category_left.id
            )
        if check_contact_type == 'c':
            partner_domain.append(('is_company', '=', True))
        if check_contact_type == 'p':
            partner_domain.append(('is_company', '=', False))
        if check_partner_category:
            partner_domain.append(
                ('category_id', 'child_of', check_partner_category))
        result['domain']['partner_id_display'] = partner_domain
        return result

    @api.one
    @api.constrains('date_start', 'date_end')
    def _check_dates(self):
        """End date should not be before start date, if not filled

        :raises exceptions.Warning: When constraint is violated
        """
        if (self.date_start and self.date_end and
                self.date_start > self.date_end):
            raise exceptions.Warning(
                _('The starting date cannot be after the ending date.')
            )

    @api.one
    @api.constrains('left_partner_id', 'type_id')
    def _check_partner_type_left(self):
        """Check left partner for required company or person

        :raises exceptions.Warning: When constraint is violated
        """
        self._check_partner_type("left")

    @api.one
    @api.constrains('right_partner_id', 'type_id')
    def _check_partner_type_right(self):
        """Check right partner for required company or person

        :raises exceptions.Warning: When constraint is violated
        """
        self._check_partner_type("right")

    @api.one
    def _check_partner_type(self, side):
        """Check partner to left or right for required company or person

        :param str side: left or right
        :raises exceptions.Warning: When constraint is violated
        """
        assert side in ['left', 'right']
        ptype = getattr(self.type_id, "contact_type_%s" % side)
        company = getattr(self, '%s_partner_id' % side).is_company
        if (ptype == 'c' and not company) or (ptype == 'p' and company):
            raise exceptions.Warning(
                _('The %s partner is not applicable for this relation type.') %
                side
            )

    @api.one
    @api.constrains('left_partner_id', 'right_partner_id')
    def _check_not_with_self(self):
        """Not allowed to link partner to same partner

        :raises exceptions.Warning: When constraint is violated
        """
        if self.left_partner_id == self.right_partner_id:
            if not self.allow_self:
                raise exceptions.Warning(
                    _('Partners cannot have a relation with themselves.')
                )

    @api.one
    @api.constrains('left_partner_id', 'right_partner_id', 'active')
    def _check_relation_uniqueness(self):
        """Forbid multiple active relations of the same type between the same
        partners

        :raises exceptions.Warning: When constraint is violated
        """
        if not self.active:
            return
        domain = [
            ('type_id', '=', self.type_id.id),
            ('active', '=', True),
            ('id', '!=', self.id),
            ('left_partner_id', '=', self.left_partner_id.id),
            ('right_partner_id', '=', self.right_partner_id.id),
        ]
        if self.date_start:
            domain += ['|', ('date_end', '=', False),
                            ('date_end', '>=', self.date_start)]
        if self.date_end:
            domain += ['|', ('date_start', '=', False),
                            ('date_start', '<=', self.date_end)]
        if self.search(domain):
            raise exceptions.Warning(
                _('There is already a similar relation with overlapping dates')
            )

    def get_action_related_partners(self, cr, uid, ids, context=None):
        '''return a window action showing a list of partners taking part in the
        relations names by ids. Context key 'partner_relations_show_side'
        determines if we show 'left' side, 'right' side or 'all' (default)
        partners.
        If active_model is res.partner.relation.all, left=this and
        right=other'''
        if context is None:
            context = {}

        field_names = {}

        if context.get('active_model', self._name) == self._name:
            field_names = {
                'left': ['left'],
                'right': ['right'],
                'all': ['left', 'right']
            }
        elif context.get('active_model') == 'res.partner.relation.all':
            field_names = {
                'left': ['this'],
                'right': ['other'],
                'all': ['this', 'other']
            }
        else:
            assert False, 'Unknown active_model!'

        partner_ids = []
        field_names = field_names[
            context.get('partner_relations_show_side', 'all')]
        field_names = ['%s_partner_id' % n for n in field_names]

        for relation in self.pool[context.get('active_model')].read(
                cr, uid, ids, context=context, load='_classic_write'):
            for name in field_names:
                partner_ids.append(relation[name])

        return {
            'name': _('Related partners'),
            'type': 'ir.actions.act_window',
            'res_model': 'res.partner',
            'domain': [('id', 'in', partner_ids)],
            'views': [(False, 'tree'), (False, 'form')],
            'view_type': 'form'
        }
class PurchaseCreditCardConciliation(models.Model):   # Maneja las acciones al cambiar sus estados

    _name = 'purchase.credit.card.conciliation'

    @api.depends('fee_ids')
    def _get_conciliation_total(self):
        for each in self:
            each.amount = sum(fee.amount for fee in each.fee_ids)

    name = fields.Char(
        'Nombre',
        required=True
    )
    date = fields.Date(
        'Fecha de conciliación',
        required=True
    )
    date_from = fields.Date(
        'Fecha desde',
        required=True
    )
    date_to = fields.Date(
        'Fecha hasta',
        required=True
    )
    journal_id = fields.Many2one(
        'account.journal',
        'Cuenta Bancaria',
        required=True,
        ondelete='restrict'
    )
    credit_card_id = fields.Many2one(
        'credit.card',
        'Tarjeta',
        required=True,
        ondelete='restrict'
    )
    amount = fields.Monetary(
        'Importe total',
        compute='_get_conciliation_total',
    )
    currency_id = fields.Many2one(
        'res.currency',
        'Moneda'
    )
    fee_ids = fields.Many2many(
        'purchase.credit.card.fee',
        'credit_card_fee_conciliation_rel',
        'conciliation_id',
        'fee_id',
        string='Cuotas'
    )
    state = fields.Selection(
        [('canceled', 'Cancelada'),
         ('draft', 'Borrador'),
         ('reconciled', 'Conciliada')],
        string='Estado',
        default='draft',
    )
    move_id = fields.Many2one(
        'account.move',
        'Asiento contable',
        readonly=True,
        ondelete='restrict'
    )
    company_id = fields.Many2one(
        'res.company',
        string='Compania',
        required=True,
        default=lambda self: self.env.user.company_id,
    )

    _sql_constraints = [('name_uniq', 'unique(name)', 'El nombre de la conciliacion debe ser unico')]
    _order = "date_from desc, name desc"

    @api.constrains('date_from', 'date_to')
    def constraint_dates(self):
        for conciliation in self:
            if conciliation.date_from > conciliation.date_to:
                raise ValidationError("La fecha desde debe ser menor que la fecha hasta.")

    @api.constrains('fee_ids')
    def constraint_fees(self):
        for conciliation in self:
            if len(conciliation.fee_ids.mapped('currency_id')) > 1:
                raise ValidationError("Las conciliaciones deben ser de cuotas en la misma moneda.")
            if len(conciliation.fee_ids.mapped('credit_card_id')) > 1:
                raise ValidationError("Las conciliaciones deben ser de cuotas de la misma tarjeta.")

    @api.multi
    def post(self):
        for conciliation in self:
            if not conciliation.fee_ids:
                raise ValidationError("No se puede validar una conciliación sin cuotas.")

            conciliation.write({
                # Ya validamos en el constraint que la moneda es unica
                'currency_id': conciliation.fee_ids.mapped('currency_id').id,
                'state': 'reconciled'
            })
            conciliation.move_id = conciliation.create_move()
            conciliation.fee_ids.reconcile()

    @api.multi
    def cancel(self):
        for conciliation in self:
            move = conciliation.move_id
            conciliation.move_id = None
            move.button_cancel()
            move.unlink()
            conciliation.fee_ids.cancel_reconcile()
            conciliation.state = 'canceled'

    @api.multi
    def cancel_to_draft(self):
        self.write({'state': 'draft'})
示例#22
0
class WebsiteSupportTicketUsers(models.Model):

    _inherit = "res.users"

    cat_user_ids = fields.Many2many('website.support.ticket.categories',
                                    string="Category Users")
示例#23
0
class ProjectForecast(models.Model):
    _inherit = ['project.forecast']

    planned_time = fields.Selection([('am', 'AM'), ('pm', 'PM'),
                                     ('am_pm', 'AM+PM'),
                                     ('specific', 'Specific time')],
                                    string='Planned on')
    issue_ids = fields.Many2many('project.issue',
                                 string="Issues",
                                 domain="[('project_id', '=', project_id)]")
    task_ids = fields.Many2many('project.task',
                                string="Tasks",
                                domain="[('project_id', '=', project_id)]")
    leave_id = fields.Many2one(
        'hr.holidays',
        string="Leave",
        domain="[('type', '=', 'remove'), ('user_id', '=', user_id)]")
    project_id = fields.Many2one('project.project', string="Project")
    comment = fields.Text(string="Comment")

    tasks_planned_hours = fields.Float(string="Planned time on tasks",
                                       compute='_compute_total_planned_hours')

    @api.multi
    @api.onchange('task_ids')
    def _compute_total_planned_hours(self):
        for forecast in self:
            forecast.tasks_planned_hours = 0
            for task in forecast.task_ids:
                forecast.tasks_planned_hours += task.planned_hours

    @api.one
    @api.onchange('planned_time')
    def planned_time_changed(self):
        calendar_ids = self.env['resource.calendar'].search([
            ('company_id', '=', self.user_id.company_id.id)
        ])

        worktime = {'morning': 8.5, 'midday': 13.5, 'evening': 17.5}

        start_date = datetime.strptime(self.start_date,
                                       DEFAULT_SERVER_DATETIME_FORMAT)
        end_date = datetime.strptime(self.end_date,
                                     DEFAULT_SERVER_DATETIME_FORMAT)

        if len(calendar_ids) > 0:
            for attendance in calendar_ids.attendance_ids:
                if int(attendance.dayofweek) == start_date.weekday():
                    worktime['morning'] = attendance.hour_from
                    worktime['midday'] = (attendance.hour_to +
                                          attendance.hour_from) / 2
                    worktime['evening'] = attendance.hour_to
                    break

        if self.planned_time == 'am':
            self.start_date = start_date.replace(hour=int(worktime['morning'] -
                                                          1))
            self.end_date = end_date.replace(hour=int(worktime['midday'] - 1))
        elif self.planned_time == 'pm':
            self.start_date = start_date.replace(hour=int(worktime['midday'] -
                                                          1))
            self.end_date = end_date.replace(hour=int(worktime['evening'] - 1))
        elif self.planned_time == 'am_pm':
            self.start_date = start_date.replace(hour=int(worktime['morning'] -
                                                          1))
            self.end_date = start_date.replace(hour=int(worktime['evening'] -
                                                        1))

    @api.one
    @api.onchange('leave_id')
    def leave_changed(self):
        if self.leave_id:
            self.start_date = self.leave_id.date_from
            self.end_date = self.leave_id.date_to
示例#24
0
class L10nEsAeatReport(models.AbstractModel):
    _name = "l10n.es.aeat.report"
    _description = "AEAT report base module"
    _rec_name = 'name'
    _aeat_number = False
    _period_quarterly = True
    _period_monthly = True
    _period_yearly = False

    def _default_company(self):
        company_obj = self.env['res.company']
        return company_obj._company_default_get('l10n.es.aeat.report')

    def _default_journal(self):
        return self.env['account.journal'].search(
            [('type', '=', 'general')])[:1]

    def get_period_type_selection(self):
        period_types = []
        if self._period_yearly:
            period_types += [('0A', '0A - Anual')]
        if self._period_quarterly:
            period_types += [('1T', '1T - Primer trimestre'),
                             ('2T', '2T - Segundo trimestre'),
                             ('3T', '3T - Tercer trimestre'),
                             ('4T', '4T - Cuarto trimestre')]
        if self._period_monthly:
            period_types += [('01', '01 - Enero'),
                             ('02', '02 - Febrero'),
                             ('03', '03 - Marzo'),
                             ('04', '04 - Abril'),
                             ('05', '05 - Mayo'),
                             ('06', '06 - Junio'),
                             ('07', '07 - Julio'),
                             ('08', '08 - Agosto'),
                             ('09', '09 - Septiembre'),
                             ('10', '10 - Octubre'),
                             ('11', '11 - Noviembre'),
                             ('12', '12 - Diciembre')]
        return period_types

    def _default_period_type(self):
        selection = self.get_period_type_selection()
        return selection and selection[0][0] or False

    company_id = fields.Many2one(
        'res.company', string='Company', required=True, readonly=True,
        default=_default_company, states={'draft': [('readonly', False)]})
    company_vat = fields.Char(
        string='VAT number', size=9, required=True, readonly=True,
        states={'draft': [('readonly', False)]})
    number = fields.Char(
        string='Declaration number', size=13, required=True, readonly=True)
    previous_number = fields.Char(
        string='Previous declaration number', size=13,
        states={'done': [('readonly', True)]})
    contact_name = fields.Char(
        string="Full Name", size=40, help="Must have name and surname.",
        states={'calculated': [('required', True)],
                'confirmed': [('readonly', True)]})
    contact_phone = fields.Char(
        string="Phone", size=9, states={'calculated': [('required', True)],
                                        'confirmed': [('readonly', True)]})
    representative_vat = fields.Char(
        string='L.R. VAT number', size=9,
        help="Legal Representative VAT number.",
        states={'confirmed': [('readonly', True)]})
    fiscalyear_id = fields.Many2one(
        'account.fiscalyear', string='Fiscal year', required=True,
        readonly=True, states={'draft': [('readonly', False)]})
    type = fields.Selection(
        [('N', 'Normal'), ('C', 'Complementary'), ('S', 'Substitutive')],
        string='Statement Type', default='N', readonly=True, required=True,
        states={'draft': [('readonly', False)]})
    support_type = fields.Selection(
        [('C', 'DVD'), ('T', 'Telematics')], string='Support Type',
        default='T', states={'calculated': [('required', True)],
                             'done': [('readonly', True)]})
    calculation_date = fields.Datetime(string="Calculation date")
    state = fields.Selection(
        [('draft', 'Draft'),
         ('calculated', 'Processed'),
         ('done', 'Done'),
         ('posted', 'Posted'),
         ('cancelled', 'Cancelled')], string='State', readonly=True,
        default='draft')
    name = fields.Char(string="Report identifier", size=13, oldname='sequence')
    model = fields.Many2one(
        comodel_name="ir.model", compute='_compute_report_model')
    export_config = fields.Many2one(
        comodel_name='aeat.model.export.config', string='Export config',
        domain="[('model', '=', model)]")
    period_type = fields.Selection(
        selection="get_period_type_selection", string="Period type",
        required=True, default=_default_period_type,
        readonly=True, states={'draft': [('readonly', False)]})
    periods = fields.Many2many(
        comodel_name='account.period', readonly=True, string="Period(s)",
        states={'draft': [('readonly', False)]})
    allow_posting = fields.Boolean(compute="_compute_allow_posting")
    counterpart_account = fields.Many2one(
        comodel_name="account.account",
        help="This account will be the counterpart for all the journal items "
             "that are regularized when posting the report.")
    journal_id = fields.Many2one(
        comodel_name="account.journal", string="Journal",
        domain=[('type', '=', 'general')], default=_default_journal,
        help="Journal in which post the move.")
    move_id = fields.Many2one(
        comodel_name="account.move", string="Account entry")
    partner_bank_id = fields.Many2one(
        comodel_name='res.partner.bank', string='Bank account',
        help='Company bank account used for the presentation',
        domain="[('state', '=', 'iban'), ('company_id', '=', company_id)]")

    _sql_constraints = [
        ('name_uniq', 'unique(name)',
         'AEAT report identifier must be unique'),
    ]

    @api.one
    def _compute_report_model(self):
        self.model = self.env['ir.model'].search([('model', '=', self._name)])

    @api.one
    def _compute_allow_posting(self):
        self.allow_posting = False

    @api.onchange('company_id')
    def on_change_company_id(self):
        """Loads some company data (the VAT number) when the selected
        company changes.
        """
        if self.company_id.vat:
            # Remove the ES part from spanish vat numbers
            #  (ES12345678Z => 12345678Z)
            self.company_vat = re.match(
                "(ES){0,1}(.*)", self.company_id.vat).groups()[1]
        self.contact_name = self.env.user.name
        self.contact_phone = self.env.user.partner_id.phone

    @api.onchange('period_type', 'fiscalyear_id')
    def onchange_period_type(self):
        period_model = self.env['account.period']
        if not self.fiscalyear_id:
            self.periods = False
        else:
            fy_date_start = fields.Date.from_string(
                self.fiscalyear_id.date_start)
            fy_date_stop = fields.Date.from_string(
                self.fiscalyear_id.date_stop)
            if self.period_type == '0A':
                # Anual
                if fy_date_start.year != fy_date_stop.year:
                    return {
                        'warning': {'title': _('Warning'), 'message': _(
                            'Split fiscal years cannot be automatically '
                            'handled. You should select manually the periods.')
                        }
                    }
                self.periods = self.fiscalyear_id.period_ids.filtered(
                    lambda x: not x.special)
            elif self.period_type in ('1T', '2T', '3T', '4T'):
                # Trimestral
                start_month = (int(self.period_type[:1]) - 1) * 3 + 1
                # Para manejar ejercicios fiscales divididos en dos periodos
                year = (fy_date_start.year if
                        start_month < fy_date_start.month else
                        fy_date_stop.year)
                period = period_model.find(
                    dt=fields.Date.to_string(
                        datetime(year=year, month=start_month, day=1)))
                period_date_stop = fields.Date.from_string(period.date_stop)
                self.periods = period
                if period_date_stop.month != start_month + 2:
                    # Los periodos no están definidos trimestralmente
                    for i in range(1, 3):
                        month = start_month + i
                        period = period_model.find(
                            dt=fields.Date.to_string(
                                datetime(year=year, month=month, day=1)))
                        self.periods += period
            elif self.period_type in ('01', '02', '03', '04', '05', '06',
                                      '07', '08', '09', '10', '11', '12'):
                # Mensual
                month = int(self.period_type)
                # Para manejar ejercicios fiscales divididos en dos periodos
                year = (fy_date_start.year if month < fy_date_start.month else
                        fy_date_stop.year)
                period = period_model.find(
                    dt=fields.Date.to_string(
                        datetime(year=year, month=month, day=1)))
                period_date_start = fields.Date.from_string(period.date_start)
                period_date_stop = fields.Date.from_string(period.date_stop)
                if period_date_start.month != period_date_stop.month:
                    return {
                        'warning': {'title': _('Warning'), 'message': _(
                            'It seems that you have defined quarterly periods '
                            'or periods in the middle of the month. This '
                            'cannot be automatically handled. You should '
                            'select manually the periods.')
                            }
                    }
                self.periods = period

    @api.model
    def _report_identifier_get(self, vals):
        seq_obj = self.env['ir.sequence']
        seq_name = "aeat%s-sequence" % self._model._aeat_number
        company_id = vals.get('company_id', self.env.user.company_id.id)
        seqs = seq_obj.search([('name', '=', seq_name),
                               ('company_id', '=', company_id)])
        return seq_obj.next_by_id(seqs.id)

    @api.model
    def create(self, vals):
        if not vals.get('name'):
            vals['name'] = self._report_identifier_get(vals)
        return super(L10nEsAeatReport, self).create(vals)

    @api.multi
    def button_calculate(self):
        res = self.calculate()
        self.write({'state': 'calculated',
                    'calculation_date': fields.Datetime.now()})
        return res

    @api.multi
    def button_recalculate(self):
        self.write({'calculation_date': fields.Datetime.now()})
        return self.calculate()

    @api.multi
    def _get_previous_fiscalyear_reports(self, date):
        """Get the AEAT reports previous to the given date.
        :param date: Date for looking for previous reports.
        :return: Recordset of the previous AEAT reports. None if there is no
        previous reports.
        """
        self.ensure_one()
        prev_periods = self.fiscalyear_id.period_ids.filtered(
            lambda x: not x.special and x.date_start < date)
        prev_reports = None
        for period in prev_periods:
            reports = self.search([('periods', '=', period.id)])
            if not reports:
                raise exceptions.Warning(
                    _("There's a missing previous declaration for the period "
                      "%s.") % period.name)
            if not prev_reports:
                prev_reports = reports
            else:
                prev_reports |= reports
        return prev_reports

    @api.multi
    def calculate(self):
        for report in self:
            if not report.periods:
                raise exceptions.Warning(
                    _('There is no period defined for the report. Please set '
                      'at least one period and try again.'))
        return True

    @api.multi
    def button_confirm(self):
        """Set report status to done."""
        self.write({'state': 'done'})
        return True

    @api.multi
    def _prepare_move_vals(self):
        self.ensure_one()
        return {
            'date': fields.Date.today(),
            'journal_id': self.journal_id.id,
            'period_id': self.env['account.period'].find().id,
            'ref': self.name,
            'company_id': self.company_id.id,
        }

    @api.multi
    def button_post(self):
        """Create any possible account move and set state to posted."""
        self.create_regularization_move()
        self.write({'state': 'posted'})
        return True

    @api.multi
    def button_cancel(self):
        """Set report status to cancelled."""
        self.write({'state': 'cancelled'})
        return True

    @api.multi
    def button_unpost(self):
        """Remove created account move and set state to done."""
        self.mapped('move_id').unlink()
        self.write({'state': 'cancelled'})
        return True

    @api.multi
    def button_recover(self):
        """Set report status to draft and reset calculation date."""
        self.write({'state': 'draft', 'calculation_date': None})
        return True

    @api.multi
    def button_export(self):
        for report in self:
            export_obj = self.env[
                "l10n.es.aeat.report.%s.export_to_boe" % report.number]
            export_obj.export_boe_file(report)
        return True

    @api.multi
    def button_open_move(self):
        self.ensure_one()
        action = self.env.ref('account.action_move_line_form').read()[0]
        action['view_mode'] = 'form'
        action['res_id'] = self.move_id.id
        del action['view_id']
        del action['views']
        return action

    @api.multi
    def unlink(self):
        if any(item.state not in ['draft', 'cancelled'] for item in self):
            raise exceptions.Warning(_("Only reports in 'draft' or "
                                       "'cancelled' state can be removed"))
        return super(L10nEsAeatReport, self).unlink()

    def init(self, cr):
        # TODO: Poner en el _register_hook para evitar choque en multi BDs
        if self._name not in ('l10n.es.aeat.report',
                              'l10n.es.aeat.report.tax.mapping'):
            seq_obj = self.pool['ir.sequence']
            try:
                aeat_num = getattr(self, '_aeat_number')
                if not aeat_num:
                    raise Exception()
                sequence = "aeat%s-sequence" % aeat_num
                if not seq_obj.search(cr, SUPERUSER_ID,
                                      [('name', '=', sequence)]):
                    seq_vals = {'name': sequence,
                                'code': 'aeat.sequence.type',
                                'number_increment': 1,
                                'implementation': 'no_gap',
                                'padding': 13 - len(str(aeat_num)),
                                'number_next_actual': 1,
                                'prefix': aeat_num
                                }
                    seq_obj.create(cr, SUPERUSER_ID, seq_vals)
            except:
                raise exceptions.Warning(
                    "Modelo no válido: %s. Debe declarar una variable "
                    "'_aeat_number'" % self._name)
示例#25
0
class IssueInvoiceWizard(models.TransientModel):
    _name = 'project.issue.invoice.account.wizard'

    def create_invoice_lines(self, invoice_dict, sales):
        task_obj = self.pool.get('project.task')
        invoice_obj = self.env['account.invoice']
        sale_line = self.env['sale.order.line']
        user = self.env['res.users'].browse(self._uid)
        invoices_list = []
        invoices_list_extra = []
        count_lines = 1
        first_line_extra = 0
        count_lines_extra = 1
        limit_lines = user.company_id.maximum_invoice_lines
        inv = invoice_obj.create(invoice_dict)
        sales.write({'invoice_ids': [(4, inv.id)]})
        invoices_list.append(inv.id)
        for sale in sales:
            for line in sale.order_line:
                if (not line.invoiced) and (line.state
                                            not in ('draft', 'cancel')):
                    line_id = line.invoice_line_create()
                    if count_lines <= limit_lines or limit_lines == 0 or limit_lines == -1:
                        inv.write({'invoice_line': [(4, line_id[0])]})
                        count_lines += 1
                    else:
                        inv = invoice_obj.create(invoice_dict)
                        sale.write({'invoice_ids': [(4, inv.id)]})
                        invoices_list.append(inv.id)
                        count_lines = 1
                        inv.write({'invoice_line': [(4, line_id[0])]})
                        count_lines += 1
            for task in sale.task_ids:
                if not task.invoice_id:
                    if task.is_closed == False:
                        raise Warning(
                            _('Task pending for close in the sale order %s' %
                              sale.name))
                    else:
                        account_id = sale.order_line[
                            0].product_id.property_account_income.id
                        if not account_id:
                            account_id = sale.order_line[
                                0].product_id.categ_id.property_account_income_categ.id
                            if not account_id:
                                prop = self.env['ir.property'].get(
                                    'property_account_income_categ',
                                    'product.category')
                                account_id = prop and prop.id or False
                        invoice_line = {
                            'name': task.name,
                            'quantity': 1,
                            'price_unit': 0,
                            'discount': sale.project_id.to_invoice.factor,
                            'account_analytic_id': sale.project_id.id,
                            'account_id': account_id,
                            'sequence': 100
                        }
                        if task.extra == True:
                            if first_line_extra == 0:
                                inv2 = invoice_obj.create(invoice_dict)
                                invoices_list_extra.append(inv2.id)
                                first_line_extra = +1
                            if count_lines_extra <= limit_lines or limit_lines == 0 or limit_lines == -1:
                                inv2.write(
                                    {'invoice_line': [(0, 0, invoice_line)]})
                                count_lines += 1
                            else:
                                inv2 = invoice_obj.create(invoice_dict)
                                sales.write({'invoice_ids': [(4, inv2.id)]})
                                invoices_list_extra.append(inv2.id)
                                count_lines = 1
                                inv2.write(
                                    {'invoice_line': [(0, 0, invoice_line)]})
                                count_lines += 1
                        for timesheet in task.timesheet_ids:
                            for account_line in timesheet.line_id:
                                if not account_line.invoice_id:
                                    if task.extra == True:
                                        account_line.write(
                                            {'invoice_id': inv2.id})
                                    else:
                                        account_line.write(
                                            {'invoice_id': inv.id})
                        for backorder in task.backorder_ids:
                            if backorder.delivery_note_id and backorder.picking_type_id.code == 'outgoing' and backorder.delivery_note_id.state == 'done' and backorder.invoice_state != 'invoiced' and backorder.state == 'done':
                                backorder.write({'invoice_state': 'invoiced'})
                                backorder.move_lines.write(
                                    {'invoice_state': 'invoiced'})
                                backorder.delivery_note_id.write(
                                    {'state': 'invoiced'})
                                if task.extra == True:
                                    for invoice in invoices_list_extra:
                                        backorder.delivery_note_id.write(
                                            {'invoice_ids': [(4, invoice)]})
                                else:
                                    for invoice in invoices_list:
                                        backorder.delivery_note_id.write(
                                            {'invoice_ids': [(4, invoice)]})
                        for expense_line in task.expense_line_ids:
                            if expense_line.expense_id.state == 'done' or expense_line.expense_id.state == 'paid':
                                for move_lines in expense_line.expense_id.account_move_id.line_id:
                                    for lines in move_lines.analytic_lines:
                                        if lines.account_id == expense_line.analytic_account and lines.name == expense_line.name and lines.unit_amount == expense_line.unit_quantity and (
                                                lines.amount * -1 /
                                                lines.unit_amount
                                        ) == expense_line.unit_amount and not lines.invoice_id:
                                            if task.extra == True:
                                                lines.write(
                                                    {'invoice_id': inv2.id})
                                            else:
                                                lines.write(
                                                    {'invoice_id': inv.id})
                        if task.extra == True:
                            task_obj.write(self._cr, self._uid, task.id,
                                           {'invoice_id': inv2.id})
                        else:
                            task_obj.write(self._cr, self._uid, task.id,
                                           {'invoice_id': inv.id})
        return invoices_list + invoices_list_extra

    @api.multi
    def generate_invoice_sale_order(self, sale_orders):
        result = {}
        invoice_sale = []
        order_obj = self.pool.get('sale.order')
        for sale in sale_orders:
            if sale.partner_id and sale.partner_id.property_payment_term.id:
                pay_term = sale.partner_id.property_payment_term.id
            else:
                pay_term = False
            inv = {
                'name':
                sale.client_order_ref or '',
                'origin':
                sale.name,
                'type':
                'out_invoice',
                'reference':
                "P%dSO%d" % (sale.partner_id.id, sale.id),
                'account_id':
                sale.partner_id.property_account_receivable.id,
                'partner_id':
                sale.partner_invoice_id.id,
                'currency_id':
                sale.pricelist_id.currency_id.id,
                'comment':
                sale.note,
                'payment_term':
                pay_term,
                'fiscal_position':
                sale.fiscal_position.id
                or sale.partner_id.property_account_position.id,
                'user_id':
                sale.user_id and sale.user_id.id or False,
                'company_id':
                sale.company_id and sale.company_id.id or False,
                'date_invoice':
                fields.date.today()
            }
            invoice_sale += self.create_invoice_lines(inv, sale)
            sale.write({'state': 'progress'})
        return invoice_sale

    @api.multi
    def generate_preventive_check(self, contracts):
        issue_obj = self.env['project.issue']
        invoice_obj = self.env['account.invoice']
        account_payment_term_obj = self.env['account.payment.term']
        currency_obj = self.env['res.currency']
        ctx = dict(self._context)
        invoices_list = []
        for contract in contracts:
            account_id = contract.product_id.property_account_income.id or contract.product_id.categ_id.property_account_income_categ.id
            if contract.invoice_partner_type == 'branch':
                for branch in contract.branch_ids:
                    if branch.property_product_pricelist:
                        if contract.pricelist_id.currency_id.id != branch.property_product_pricelist.currency_id.id:
                            import_currency_rate = contract.pricelist_id.currency_id.get_exchange_rate(
                                branch.property_product_pricelist.currency_id,
                                date.strftime(date.today(), "%Y-%m-%d"))[0]
                        else:
                            import_currency_rate = 1
                    else:
                        if contract.pricelist_id.currency_id.id != contract.company_id.currency_id.id:
                            import_currency_rate = contract.pricelist_id.currency_id.get_exchange_rate(
                                contract.company_id.currency_id,
                                date.strftime(date.today(), "%Y-%m-%d"))[0]
                        else:
                            import_currency_rate = 1
                    date_due = False
                    if branch.property_payment_term:
                        pterm_list = account_payment_term_obj.compute(
                            branch.property_payment_term.id,
                            value=1,
                            date_ref=time.strftime('%Y-%m-%d'))
                        if pterm_list:
                            pterm_list = [line[0] for line in pterm_list]
                            pterm_list.sort()
                            date_due = pterm_list[-1]
                    invoice = {
                        'partner_id':
                        branch.id,
                        'company_id':
                        contract.company_id.id,
                        'payment_term':
                        branch.property_payment_term.id,
                        'account_id':
                        branch.property_account_receivable.id,
                        'name':
                        contract.name,
                        'currency_id':
                        branch.property_product_pricelist.currency_id.id
                        or contract.company_id.currency_id.id,
                        'fiscal_position':
                        branch.property_account_position.id,
                        'date_due':
                        date_due
                    }
                    ctx = dict(self._context)
                    ctx['lang'] = branch.lang
                    ctx['force_company'] = contract.company_id.id
                    ctx['company_id'] = contract.company_id.id
                    self = self.with_context(ctx)
                    inv = invoice_obj.create(invoice)
                    invoices_list.append(inv.id)
                    invoice_line = {
                        'product_id':
                        contract.product_id.id,
                        'name':
                        contract.name,
                        'quantity':
                        1,
                        'price_unit':
                        contract.amount_preventive_check *
                        import_currency_rate,
                        'discount':
                        contract.to_invoice.factor,
                        'account_analytic_id':
                        contract.id,
                        'invoice_line_tax_id':
                        [(6, 0,
                          [tax.id for tax in contract.product_id.taxes_id])],
                        'account_id':
                        account_id
                    }
                    inv.write({'invoice_line': [(0, 0, invoice_line)]})
            elif contract.invoice_partner_type == 'customer':
                date_due = False
                if contract.partner_id.property_product_pricelist:
                    if contract.pricelist_id.currency_id.id != contract.partner_id.property_product_pricelist.currency_id.id:
                        import_currency_rate = contract.pricelist_id.currency_id.get_exchange_rate(
                            contract.partner_id.
                            property_product_pricelist.currency_id,
                            date.strftime(date.today(), "%Y-%m-%d"))[0]
                    else:
                        import_currency_rate = 1
                else:
                    if contract.pricelist_id.currency_id.id != contract.company_id.currency_id.id:
                        import_currency_rate = contract.pricelist_id.currency_id.get_exchange_rate(
                            contract.company_id.currency_id,
                            date.strftime(date.today(), "%Y-%m-%d"))[0]
                    else:
                        import_currency_rate = 1
                if contract.partner_id.property_payment_term:
                    pterm_list = account_payment_term_obj.compute(
                        contract.partner_id.property_payment_term.id,
                        value=1,
                        date_ref=time.strftime('%Y-%m-%d'))
                    if pterm_list:
                        pterm_list = [line[0] for line in pterm_list]
                        pterm_list.sort()
                        date_due = pterm_list[-1]
                invoice = {
                    'partner_id':
                    contract.partner_id.id,
                    'company_id':
                    contract.company_id.id,
                    'payment_term':
                    contract.partner_id.property_payment_term.id,
                    'account_id':
                    contract.partner_id.property_account_receivable.id,
                    'name':
                    contract.name,
                    'currency_id':
                    contract.company_id.currency_id.id,
                    'fiscal_position':
                    contract.partner_id.property_account_position.id,
                    'date_due':
                    date_due
                }
                ctx = dict(self._context)
                ctx['lang'] = contract.partner_id.lang
                ctx['force_company'] = contract.company_id.id
                ctx['company_id'] = contract.company_id.id
                self = self.with_context(ctx)
                inv = invoice_obj.create(invoice)
                invoices_list.append(inv.id)
                invoice_line = {
                    'product_id':
                    contract.product_id.id,
                    'name':
                    contract.name,
                    'quantity':
                    1,
                    'price_unit':
                    contract.amount_preventive_check * import_currency_rate,
                    'discount':
                    contract.to_invoice.factor,
                    'account_analytic_id':
                    contract.id,
                    'invoice_line_tax_id':
                    [(6, 0, [tax.id for tax in contract.product_id.taxes_id])],
                    'account_id':
                    account_id
                }
                inv.write({'invoice_line': [(0, 0, invoice_line)]})
            for issue in issue_obj.search([('stage_id.closed', '=', True),
                                           ('sale_order_id', '=', False),
                                           ('invoice_ids', '=', False),
                                           ('analytic_account_id', '=',
                                            contract.id)]):
                inv.write({'issue_ids': [(4, issue.id)]})
        return invoices_list

    def get_next_execute_preventive_check(self, contract):
        next_date_execute = False
        if contract.preventive_check_invoice_date:
            if contract.preventive_check_interval_type == 'days':
                next_date_execute = datetime.strptime(
                    contract.preventive_check_invoice_date,
                    '%Y-%m-%d') + relativedelta(
                        days=+contract.preventive_check_interval_number)
            elif contract.preventive_check_interval_type == 'weeks':
                next_date_execute = datetime.strptime(
                    contract.preventive_check_invoice_date,
                    '%Y-%m-%d') + relativedelta(
                        weeks=+contract.preventive_check_interval_number)
            elif contract.preventive_check_interval_type == 'months':
                next_date_execute = datetime.strptime(
                    contract.preventive_check_invoice_date,
                    '%Y-%m-%d') + relativedelta(
                        months=+contract.preventive_check_interval_number)
        else:
            next_date_execute = False
        return next_date_execute.date()

    @api.multi
    def validate_contracts(self):
        account_analytic_list = []
        partner_ids = []
        issue_ids = []
        model_ids = []
        issue_obj = self.env['project.issue']
        contracts = self.env['account.analytic.account'].search([
            '|', ('invoice_on_timesheets', '=', True),
            ('charge_expenses', '=', True),
            ('id', 'in', self._context.get('active_ids'))
        ])
        if contracts:
            if self.filter == 'filter_no':
                issue_ids = issue_obj.search(
                    [
                        '|', '|', ('backorder_ids', '!=', False),
                        ('expense_line_ids', '!=', False),
                        ('timesheet_ids', '!=', False),
                        ('issue_type', '!=', 'preventive check'),
                        ('stage_id.closed', '=', True),
                        ('sale_order_id', '=', False),
                        ('invoice_ids', '=', False),
                        ('analytic_account_id', 'in',
                         self._context.get('active_ids', False))
                    ],
                    order='categ_id asc,product_id asc,create_date asc')
            elif self.filter == 'filter_date':
                issue_ids = issue_obj.search(
                    [
                        '|', '|', ('backorder_ids', '!=', False),
                        ('expense_line_ids', '!=', False),
                        ('timesheet_ids', '!=', False),
                        ('issue_type', '!=', 'preventive check'),
                        ('stage_id.closed', '=', True),
                        ('sale_order_id', '=', False),
                        ('invoice_ids', '=', False),
                        ('create_date', '>=', self.date_from),
                        ('create_date', '<=', self.date_to),
                        ('analytic_account_id', 'in',
                         self._context.get('active_ids', False))
                    ],
                    order='categ_id asc,product_id asc,create_date asc')
            elif self.filter == 'filter_period':
                issue_ids = issue_obj.search(
                    [
                        '|', '|', ('backorder_ids', '!=', False),
                        ('expense_line_ids', '!=', False),
                        ('timesheet_ids', '!=', False),
                        ('issue_type', '!=', 'preventive check'),
                        ('stage_id.closed', '=', True),
                        ('sale_order_id', '=', False),
                        ('invoice_ids', '=', False),
                        ('create_date', '>=', self.period_from.date_start),
                        ('create_date', '<=', self.period_to.date_stop),
                        ('analytic_account_id', 'in',
                         self._context.get('active_ids', False))
                    ],
                    order='categ_id asc,product_id asc,create_date asc')
            elif self.filter == 'filter_partner':
                for partner in self.partner_ids:
                    partner_ids.append(partner.id)
                issue_ids = issue_obj.search(
                    [
                        '&', '|', '|', ('backorder_ids', '!=', False),
                        ('expense_line_ids', '!=', False),
                        ('timesheet_ids', '!=', False), '|',
                        ('partner_id', 'in', partner_ids),
                        ('branch_id', 'in', partner_ids),
                        ('issue_type', '!=', 'preventive check'),
                        ('stage_id.closed', '=', True),
                        ('sale_order_id', '=', False),
                        ('invoice_ids', '=', False),
                        ('analytic_account_id', 'in',
                         self._context.get('active_ids', False))
                    ],
                    order='categ_id asc,product_id asc,create_date asc')
            elif self.filter == 'filter_issue':
                for issue in self.issue_ids:
                    issue_ids.append(issue.id)
                issue_ids = issue_obj.search(
                    [
                        '|', '|', ('backorder_ids', '!=', False),
                        ('expense_line_ids', '!=', False),
                        ('timesheet_ids', '!=', False),
                        ('issue_type', '!=', 'preventive check'),
                        ('stage_id.closed', '=', True),
                        ('sale_order_id', '=', False),
                        ('invoice_ids', '=', False), ('id', 'in', issue_ids),
                        ('analytic_account_id', 'in',
                         self._context.get('active_ids', False))
                    ],
                    order='categ_id asc,product_id asc,create_date asc')
            self.issue_invoice_ids = issue_ids
        else:
            self.issue_invoice_ids = False
        self.write({'state': 'done'})
        return {
            'name': _('Issues to Invoice'),
            'type': 'ir.actions.act_window',
            'res_model': self._name,
            'view_type': 'form',
            'view_mode': 'form',
            'target': 'new',
            'res_id': self.id,
            'context': self._context
        }

    @api.multi
    def invoice_contracts(self):
        wizard_obj = self.env['project.issue.helpdesk.invoice.wizard']
        invoices_list_issues = []
        issue_list = []
        invoice_sale_list = []
        invoice_preventive_check_list = []
        if self.issue_invoice_ids:
            for issue in self.issue_invoice_ids:
                issue_list.append(issue.id)
            invoices_list_issues = wizard_obj.generate_invoices(
                self.issue_invoice_ids, issue_list, self.group_customer,
                self.line_detailed)
        if self.sale_order_invoice_ids:
            invoice_sale_list = self.generate_invoice_sale_order(
                self.sale_order_invoice_ids)
        if self.contract_preventive_check_ids:
            invoice_preventive_check_list = self.generate_preventive_check(
                self.contract_preventive_check_ids)

        result = self.env['ir.model.data'].get_object_reference(
            'account', 'action_invoice_tree1')
        id = result and result[1] or False
        act_win = self.env['ir.actions.act_window'].search_read([('id', '=',
                                                                  id)])[0]
        act_win['domain'] = [
            ('id', 'in', invoices_list_issues + invoice_sale_list +
             invoice_preventive_check_list), ('type', '=', 'out_invoice')
        ]
        act_win['name'] = _('Invoices')
        return act_win

    @api.one
    @api.constrains('date_from', 'date_to')
    def _check_filter_date(self):
        if self.filter == 'filter_date':
            if self.date_from > self.date_to:
                raise Warning(_('Start Date must be less than End Date'))

    @api.constrains('period_from', 'period_to')
    def _check_filter_period(self):
        if self.filter == 'filter_period':
            if self.period_from.date_start > self.period_to.date_stop:
                raise Warning(_('Start Period must be less than End Period'))

    @api.onchange('filter')
    def get_account_issues(self):
        contracts = self.env['account.analytic.account'].search([
            '|', ('invoice_on_timesheets', '=', True),
            ('charge_expenses', '=', True),
            ('id', 'in', self._context.get('active_ids'))
        ])
        if contracts:
            if self.filter == 'filter_issue':
                self.init_onchange_call = self.env['project.issue'].search([
                    '|', '|', ('backorder_ids', '!=', False),
                    ('expense_line_ids', '!=', False),
                    ('timesheet_ids', '!=', False),
                    ('issue_type', '!=', 'preventive check'),
                    ('stage_id.closed', '=', True),
                    ('sale_order_id', '=', False), ('invoice_ids', '=', False),
                    ('analytic_account_id', 'in',
                     self._context.get('active_ids', False))
                ])
            else:
                self.issue_ids = False
        else:
            self.issue_ids = False

    @api.onchange('state')
    def get_account(self):
        if 'active_ids' in self._context and self._context.get('active_ids'):
            self.sale_order_invoice_ids = self.env['sale.order'].search([
                ('project_id', 'in', self._context.get('active_ids', False)),
                ('state', '=', 'manual')
            ])
            self.contract_preventive_check_ids = self.env[
                'account.analytic.account'].search([
                    ('id', 'in', self._context.get('active_ids', False)),
                    ('invoice_preventive_check', '!=', False)
                ])

    line_detailed = fields.Boolean(
        string="Product lines separate service lines", default=True)
    group_customer = fields.Boolean(string="Group by customer", default=True)
    filter = fields.Selection([('filter_no', 'No Filter'),
                               ('filter_date', 'Date'),
                               ('filter_period', 'Period'),
                               ('filter_partner', 'Partner'),
                               ('filter_issue', 'Issue')],
                              string="Filter",
                              required=True,
                              default='filter_no')
    date_from = fields.Date(string="Start Date")
    date_to = fields.Date(string="End Date")
    fiscalyear_id = fields.Many2one('account.fiscalyear', string="Fiscal Year")
    period_to = fields.Many2one('account.period', string="End Period")
    period_from = fields.Many2one('account.period', string="Start Period")
    partner_ids = fields.Many2many('res.partner', string="Customers")
    init_onchange_call = fields.Many2many('project.issue',
                                          compute="get_account_issues",
                                          string='Nothing Display',
                                          help='field at view init')
    issue_ids = fields.Many2many(
        'project.issue',
        relation='project_issue_helpdesk_account_wizard_rel',
        string="Issues")
    issue_invoice_ids = fields.Many2many(
        'project.issue',
        relation='project_issue_to_invoice_account_wizard_rel',
        string="Issues")
    sale_order_invoice_ids = fields.Many2many(
        'sale.order',
        relation='sale_order_to_invoice_account_wizard_rel',
        string="Sale Orders")
    state = fields.Selection([('validate', 'Validate'), ('done', 'Done')],
                             string='State')
    contract_preventive_check_ids = fields.Many2many(
        'account.analytic.account',
        relation='account_analytic_invoice_account_wizard_rel',
        string="Contracts")
    _defaults = {'state': 'validate'}
示例#26
0
class res_partner(models.Model):
    _inherit = 'res.partner'

    @api.model
    def _sale_communication_method_get(self):
        return [
            ('fax', _('Fax')),
            ('email', _('Email')),
        ]

    # START TO DELETE #
    @api.model
    def _sale_invoicing_trigger_get(self):
        return [
            ('picking', _('To the delivery')),
            ('manual', _('On demand')),
            ('postpaid', _('On the order')),
        ]

    # END TO DELETE #

    @api.model
    def _sale_invoiced_on_get(self):
        return [
            ('order', _('Ordered quantities')),
            ('delivery', _('Delivered quantities')),
        ]

    @api.one
    @api.depends('email', 'fax', 'sale_contact_ids',
                 'sale_communication_method', 'receipt_demand',
                 'delay_confirmation')
    def _compute_sale_communication_value(self):
        if self.sale_communication_method:
            self.sale_communication_value = self.env[
                'res.partner'].calcul_value_com(self.sale_contact_ids, self,
                                                self.sale_communication_method)
        else:
            self.sale_communication_value = ''

    @api.model
    def _sale_invoice_postage_get(self):
        return [
            ('never', _('Never')),
            ('always', _('Always')),
            ('threshold', _('< Threshold')),
        ]

    @api.one
    def _compute_type_inv_ids(self):
        partner_type_rcs = self.env['res.partner.type'].search([
            ('partner_type_id', '=', self.id)
        ])
        partner_rcs = self.env['res.partner']
        if partner_type_rcs:
            for partner_type in partner_type_rcs:
                partner_rcs |= partner_type.partner_id

        self.type_inv_ids = partner_rcs.ids

    #===========================================================================
    # COLUMNS
    #===========================================================================

    # Onglet vente
    can_order = fields.Boolean(string='Authorized to place an order',
                               default=False)
    can_be_charged = fields.Boolean(string='Authorized to be charged',
                                    default=False)
    can_be_delivered = fields.Boolean(string='Authorized to be delivered',
                                      default=False)
    can_paid = fields.Boolean(string='Authorized to paid', default=False)
    type_ids = fields.One2many('res.partner.type',
                               'partner_id',
                               string='Partners types')
    type_inv_ids = fields.Many2many('res.partner',
                                    'sale_res_partner_type_partner_rel',
                                    'partner_id',
                                    'partner_type_inv_id',
                                    string='Partners types inverse',
                                    compute='_compute_type_inv_ids')
    partial_sale_delivery = fields.Boolean(
        string='Partial delivery allowed',
        default=True,
        help='If you don\'t have enough stock available to '
        'deliver all at once, do you accept partial shipments or not?')
    generate_sale_rest = fields.Boolean(string='Allowed rest', default=True)
    receipt_demand = fields.Boolean(string='Acknowledgement or receipt demand',
                                    default=False)
    delay_confirmation = fields.Boolean(string='Delay confirmation',
                                        default=False)
    sale_contact_ids = fields.Many2many(
        'res.partner',
        'sale_contact_id_partner_rel',
        'partner_id',
        'contact_id',
        string='Contacts',
        help='If you choose a contact, '
        'the communication value will refer to its coordinates')
    sale_invoicing_method_id = fields.Many2one('account.invoicing.method',
                                               string='Invoicing method',
                                               required=False,
                                               ondelete='restrict')

    #Champ conservé pour la reprise des données, à supprimer plus tard
    sale_contact_id = fields.Many2one('res.partner',
                                      string='Contact',
                                      required=False,
                                      ondelete='restrict')
    sale_communication_method = fields.Selection(
        '_sale_communication_method_get', string='Communication method')
    sale_communication_value = fields.Char(
        string='Communication value',
        compute='_compute_sale_communication_value')
    sales_manager_id = fields.Many2one('res.users',
                                       string='Sales manager',
                                       required=False,
                                       ondelete='restrict')
    seller_id = fields.Many2one('res.users',
                                string='Seller',
                                required=False,
                                ondelete='restrict')
    stat_family_id = fields.Many2one('partner.stat.family',
                                     string='Statistics family',
                                     required=False,
                                     ondelete='restrict')
    edi_code = fields.Char(string='EDI code', size=17, required=False)
    num_with_customer = fields.Char(string='Our number with the customer',
                                    size=128,
                                    required=False)
    note_header = fields.Html(string='Note on the sale order header')
    sale_payment_method_id = fields.Many2one('payment.method',
                                             string='Payment method',
                                             required=False,
                                             ondelete='restrict')
    # START TO DELETE #
    sale_invoicing_trigger = fields.Selection(
        '_sale_invoicing_trigger_get', string='Invoicing trigger method')
    sale_invoiced_on = fields.Selection(
        '_sale_invoiced_on_get',
        string='Invoiced on',
        help='This field indicates if the invoice on the '
        'basis of quantities actually delivered or on the basis of quantities ordered (can be useful in '
        'case of flat rate, for example)')
    # END TO DELETE #
    sale_discount_management = fields.Boolean(string='Discount management',
                                              default=False)
    sale_max_delay = fields.Integer(string='Maximum delay for application',
                                    default=0,
                                    required=False,
                                    help="In days")
    sale_discount_value = fields.Float(string='Discount value',
                                       default=0.0,
                                       required=False)

    #Champ transport
    sale_incoterm_id = fields.Many2one(
        'stock.incoterms',
        string='Incoterm',
        required=False,
        ondelete='restrict',
        help='Incoterm which '
        'stands for \'International Commercial terms\' implies its a series of sales terms which are used '
        'in the commercial transaction.')
    sale_invoice_postage = fields.Selection('_sale_invoice_postage_get',
                                            string='Invoice postage type')
    sale_threshold = fields.Float(string='Threshold',
                                  default=0.0,
                                  required=False)
    sale_forwarding_agent_id = fields.Many2one('res.partner',
                                               string='Forwarding Agent',
                                               required=False,
                                               ondelete='restrict')
    sale_delivery_delay = fields.Integer(
        string='Delivery delay',
        default=0,
        required=False,
        help="Carrier delay (in working days)")
    sale_delivery_contact_id = fields.Many2one('res.partner',
                                               string='Contact',
                                               required=False,
                                               ondelete='restrict')
    note_delivery_order = fields.Html(string='Note on delivery order')

    _sql_constraints = [(
        'check_sale_partner_qualified',
        """CHECK((is_customer=true AND (state='qualified' AND ((can_be_charged = true AND sale_invoicing_method_id IS NOT NULL) OR (can_be_charged=false)) AND ((can_be_delivered = true AND property_account_position_id IS NOT NULL) OR (can_be_delivered=false)) AND ((can_paid = true AND property_payment_term_id IS NOT NULL AND sale_payment_method_id IS NOT NULL) OR (can_paid=false))) OR (state!='qualified')) OR (is_customer=false))""",
        """Some required fields are not filled, please check the form view of the partner:
                 - if the partner is delivered, you must fill the incoterm and the fiscal position,
                 - if the partner is invoiced, you must fill the invoicing method,
                 - and if the partner can pay, you must fill the payment term and the payment method.
          """)]

    # Même contrainte que ci-dessus indenté pour lisibilité.
    #     _sql_constraints = [
    #         ('check_sale_partner_qualified',
    #          """CHECK((
    #                 is_customer=true AND (
    #                     state='qualified' AND (
    #                         (
    #                             can_be_charged = true AND
    #                             sale_invoicing_method_id IS NOT NULL
    #                         ) OR (can_be_charged=false)
    #                     )
    #                     AND (
    #                         (
    #                             can_be_delivered = true AND
    #                             property_account_position_id IS NOT NULL
    #                         ) OR (can_be_delivered=false)
    #                     )
    #                     AND (
    #                         (
    #                             can_paid = true AND
    #                             property_payment_term_id IS NOT NULL AND
    #                             sale_payment_method_id IS NOT NULL
    #                         ) OR (can_paid=false)
    #                     )
    #                 ) OR (state!='qualified')
    #             ) OR (is_customer=false))""",
    #           """Some required fields are not filled, please check the form view of the partner:
    #                  - if the partner is delivered, you must fill the incoterm and the fiscal position,
    #                  - if the partner is invoiced, you must fill the invoicing method,
    #                  - and if the partner can pay, you must fill the payment term and the payment method.
    #           """)
    #     ]

    @api.onchange('partial_sale_delivery')
    def _onchange_partial_sale_delivery(self):
        """
            Si 'Livraison incomplète' est décochée, on décoche 'Générer un reliquat'
        """
        if not self.partial_sale_delivery:
            self.generate_sale_rest = False


#
#     @api.onchange('sale_invoicing_trigger')
#     def _onchange_sale_invoicing_trigger(self):
#         """
#             Si on passe le mode de déclenchement à la commande, on sélectionne la facturation sur
#             quantités commandées
#             Si on passe le mode de déclenchement à la livraison, on sélectionne la facturation sur
#             quantités livrées
#         """
#         if self.sale_invoicing_trigger in ['manual','postpaid']:
#             self.sale_invoiced_on = 'order'
#         elif self.sale_invoicing_trigger == 'picking' and self.property_payment_term_id.payment_type != 'after_invoicing':
#             self.sale_invoiced_on = 'delivery'
#
#
#     @api.onchange('sale_invoiced_on', 'property_payment_term_id')
#     def _onchange_sale_invoiced_on(self):
#         """
#             On modifie la méthode de déclenchement de facturation en fonction du type de paiement
#             et du type de facturation (qtés livrées ou commandées)
#         """
#         if self.sale_invoiced_on == 'delivery':
#             self.sale_invoicing_trigger = 'picking'
#         elif self.sale_invoiced_on == 'order' and self.property_payment_term_id.payment_type != 'after_invoicing' and self.sale_invoicing_trigger != 'manual':
#             self.sale_invoicing_trigger = 'postpaid'

#     @api.one
#     @api.constrains('sale_invoicing_trigger', 'sale_invoiced_on', 'property_payment_term_id', 'property_payment_term_id.payment_type')
#     def _check_sale_invoiced_on(self):
#         """
#             Verifie:
#             - que le déclenchement de la facturation soit cohérent avec le type de facturation
#             - que la facturation ne se fait pas sur les quantités livrées si la facturation est manuelle
#         """
#         if self.sale_invoiced_on == 'delivery' and self.sale_invoicing_trigger != 'picking':
#             raise Warning(_('Error ! You cannot have an invoice in the delivered quantities if the invoice trigger is not on the picking'))
#
#         if self.sale_invoiced_on == 'order':
#             if self.property_payment_term_id.payment_type in ['before_validation', 'before_delivery'] and self.sale_invoicing_trigger not in ['postpaid', 'manual']:
#                 raise Warning(_('Error ! You cannot have an invoice in the ordered quantities if the invoice trigger is not in the order or manual'))

    @api.one
    @api.constrains('partial_sale_delivery', 'generate_sale_rest')
    def _check_partial_sale_delivery(self):
        """
            Verifie que le booléen de génération de reliquat soit bien décoché si celui
            de livraison incomplète l'es aussi 
        """
        if self.is_company and not self.partial_sale_delivery and self.generate_sale_rest:
            raise Warning(
                _('Error ! You cannot generate rest if you don\'t accept partial delivery (in the sale tab)'
                  ))

        return True

    @api.one
    @api.constrains('can_order', 'can_be_charged', 'can_be_delivered',
                    'can_paid')
    def _check_sale_partner_type(self):
        """
            Dans le cas d'un contact, si celui-ci est lié à une société, la société doit avoir
            la même configuration que lui (c'est-à-dire qu'elle doit être autorisée à commander
            si le contact est autorisé à commander, autorisée à payer si le contact l'est etc...).
            Si le contact n'est pas lié à une société, les 4 booléens doivent être cochés ou aucun
            ne doit l'être
            
            Dans le cas d'une société, si elle est autorisée à commander, on doit avoir au moins
            un livreur, un facturé et un payeur.
        """
        #Cas d'un contact
        if not self.is_company:
            parent_company = self.parent_id
            #Contact avec société parente
            if parent_company:
                if self.can_be_charged and not parent_company.can_be_charged:
                    raise Warning(
                        _('Error ! If the contact can be charged, the parent company'
                          ' must be charged too'))
                if self.can_be_delivered and not parent_company.can_be_delivered:
                    raise Warning(
                        _('Error ! If the contact can be delivered, the parent company'
                          ' must be delivered too'))
                if self.can_order and not parent_company.can_order:
                    raise Warning(
                        _('Error ! If the contact can order, the parent company'
                          ' must order too'))
                if self.can_paid and not parent_company.can_paid:
                    raise Warning(
                        _('Error ! If the contact can pay, the parent company'
                          ' must pay too'))

            else:
                #Contact sans société parente
                bool_count = 0
                if self.can_be_charged:
                    bool_count += 1

                if self.can_be_delivered:
                    bool_count += 1

                if self.can_order:
                    bool_count += 1

                if self.can_paid:
                    bool_count += 1

                if bool_count != 4 and bool_count != 0:
                    raise Warning(
                        _('Error ! If the contact haven\'t a parent company, it must'
                          ' order, pay, be charged and be delivered, or none of them.'
                          ))

        else:
            #Cas d'une société qui peut commander
            if self.can_order and self.is_customer:
                delivered = False
                charged = False
                paid = False
                if self.can_be_delivered:
                    delivered = True

                if self.can_be_charged:
                    charged = True

                if self.can_paid:
                    paid = True

                for partner in self.type_ids:
                    if partner.partner_type == 'can_be_delivered':
                        delivered = True
                    elif partner.partner_type == 'can_be_charged':
                        charged = True
                    elif partner.partner_type == 'can_paid':
                        paid = True

                if not delivered or not charged or not paid:
                    raise Warning(
                        _('Error ! If the partner can order, it must be or have a payer, '
                          'a charged and a delivered.'))

        return True

    def get_partner_address(self, infos={}, return_id=False):
        """
            Fonction qui ramène toutes les adresses et les clients
            pour la livraison, la facturation, la commande et le paiement
            On passe un dictionnaire dans lequel on entre les informations souhaitées. Exemple:
            Si on ne souhaite que l'adresse de livraison, on entrera uniquement 'delivery' dans le dictionnaire
            :type self: res.partner
            :param infos: Dictionnaire contenant les informations souhaitées
            :type infos: dict
            :param return_id: True si on veut des ids, False pour des recordset
            :type return_id: boolean
            :return: Le dictionnaire contenant les informations demandées
            :rtype: dict
        """
        res = super(res_partner, self).get_partner_address(infos=infos,
                                                           return_id=return_id)
        #La fonction est en deux parties : le cas d'un partenaire client et le cas d'un contact
        # 1 - Partner client
        #On vérifie avant tout que le partner soit bien un client, sinon on renvoie un dictionnaire vide
        partner = self
        if partner:
            principal_address = return_id and partner.address_id.id or partner.address_id
            principal_customer = return_id and partner.id or partner
            res['order_address'] = principal_address
            if partner.is_company and partner.is_customer:
                #On commence par récupérer l'adresse principale du partner pour
                #la passer en tant qu'adresse de la commande
                #On regarde ensuite si le partner peut être livré. Si c'est le cas,
                #on renvoie son adresse principale et l'id du partner
                if infos.get('delivery'):
                    if partner.can_be_delivered:
                        res['delivery_address'] = principal_address
                        res['delivery_partner'] = principal_customer
                    #Sinon, on recherche et récupère le partner ou contact livré, ainsi que
                    #son adresse principale.
                    else:
                        for line in partner.type_ids:
                            if line.partner_type == 'can_be_delivered':
                                res['delivery_partner'] = return_id and line.partner_type_id.id or line.partner_type_id
                                res['delivery_address'] = return_id and line.partner_type_id.address_id.id or line.partner_type_id.address_id
                                break

                #On regarde ensuite si le partner peut être facturé. Si c'est le cas,
                #on renvoie son adresse principale et l'id du partner
                if infos.get('invoiced'):
                    if partner.can_be_charged:
                        res['invoiced_address'] = principal_address
                        res['invoiced_partner'] = principal_customer
                    #Sinon, on recherche et récupère le partner ou contact facturé, ainsi que
                    #son adresse principale.
                    else:
                        for line in partner.type_ids:
                            if line.partner_type == 'can_be_charged':
                                res['invoiced_partner'] = return_id and line.partner_type_id.id or line.partner_type_id
                                res['invoiced_address'] = return_id and line.partner_type_id.address_id.id or line.partner_type_id.address_id
                                break

                #On regarde enfin si le partner peut être payeur. Si c'est le cas,
                #on renvoie id. Sinon, on recherche et récupère le partner ou contact payeur
                if infos.get('paid'):
                    if partner.can_paid:
                        res['pay_partner'] = principal_customer
                    else:
                        for line in partner.type_ids:
                            if line.partner_type == 'can_paid':
                                res['pay_partner'] = return_id and line.partner_type_id.id or line.partner_type_id
                                break

            # 2 - Contact
            elif not partner.is_company:
                #Si le contact n'est pas lié à un partenaire, on récupère son adresse et son id pour tous les champs
                if not partner.parent_id and partner.can_be_charged and partner.can_be_delivered and partner.can_paid \
                and partner.can_order:
                    if infos.get('delivery'):
                        res['delivery_address'] = principal_address
                        res['delivery_partner'] = principal_customer

                    if infos.get('invoiced'):
                        res['invoiced_address'] = principal_address
                        res['invoiced_partner'] = principal_customer

                    if infos.get('paid'):
                        res['pay_partner'] = principal_customer

                    res['pay_partner'] = principal_customer

                elif partner.parent_id:
                    related_partner = partner.parent_id
                    if infos.get('invoiced'):
                        if partner.can_be_charged:
                            res['invoiced_address'] = principal_address
                            res['invoiced_partner'] = principal_customer
                        elif related_partner.can_be_charged:
                            res['invoiced_address'] = return_id and related_partner.address_id.id or related_partner.address_id
                            res['invoiced_partner'] = return_id and related_partner.id or related_partner
                        else:
                            for line in related_partner.type_ids:
                                if line.partner_type == 'can_be_charged':
                                    res['invoiced_partner'] = return_id and line.partner_type_id.id or line.partner_type_id
                                    res['invoiced_address'] = return_id and line.partner_type_id.address_id.id or line.partner_type_id.address_id
                                    break

                    if infos.get('delivery'):
                        if partner.can_be_delivered:
                            res['delivery_address'] = principal_address
                            res['delivery_partner'] = principal_customer
                        elif related_partner.can_be_delivered:
                            res['delivery_address'] = related_partner.address_id and related_partner.address_id.id or False
                            res['delivery_partner'] = related_partner.id
                        else:
                            for line in related_partner.type_ids:
                                if line.partner_type == 'can_be_delivered':
                                    res['delivery_partner'] = return_id and line.partner_type_id.id or line.partner_type_id
                                    res['delivery_address'] = return_id and line.partner_type_id.address_id.id or line.partner_type_id.address_id
                                    break

                    if infos.get('paid'):
                        if partner.can_paid:
                            res['pay_partner'] = principal_customer
                        elif related_partner.can_paid:
                            res['pay_partner'] = related_partner.id
                        else:
                            for line in related_partner.type_ids:
                                if line.partner_type == 'can_paid':
                                    res['pay_partner'] = return_id and line.partner_type_id.id or line.partner_type_id
                                    break

        return res

    @api.multi
    def show_partner_sale(self):
        """
            Fonction qui cherche et retourne les ventes du partenaire
        """
        action_struc = {}
        action_dict = get_form_view(self, 'sale.action_see_all_sale_order')
        if action_dict and action_dict.get('id') and action_dict.get('type'):
            action = self.env[action_dict['type']].browse(action_dict['id'])
            action_struc = action.read()
            action_struc[0]['context'] = {'partner_id': self.id}
            action_struc = action_struc[0]

        return action_struc

    def get_sale_transport_fields(self, return_id=False):
        if self:
            res = {
                'sale_incoterm_id':
                return_id and self.sale_incoterm_id.id
                or self.sale_incoterm_id,
                'sale_invoice_postage':
                self.sale_invoice_postage,
                'sale_threshold':
                self.sale_threshold,
                'sale_forwarding_agent_id':
                return_id and self.sale_forwarding_agent_id.id
                or self.sale_forwarding_agent_id,
                'transport_delay':
                self.sale_delivery_delay,
            }
        else:
            res = {
                'sale_incoterm_id': False,
                'sale_invoice_postage': False,
                'sale_threshold': False,
                'sale_forwarding_agent_id': False,
                'transport_delay': False,
            }

        return res

    def compute_domain_args(self, args):
        #Fonction appelée par le search afin de n'afficher que les contacts inscrits dans la liste de contact
        args2 = []
        partner_type_obj = self.env['res.partner.type']
        partner_obj = self.env['res.partner']
        for arg in args:
            match = False
            if isinstance(arg, str) or (isinstance(arg, list)
                                        and arg[0] in ('!', '|', '&')):
                args2.append(arg)
                continue

            if arg[0] == 'contact_in_partner_sale':
                arg[0] = 'id'
                arg[-1] = [x[1] for x in arg[-1] if x[0] != 2]
            elif arg[0] == 'partner_contact_sale_order':
                arg[0] = 'id'
                arg[1] = 'in'
                partner_id = arg[-1]
                arg[-1] = []
                for contact in self.browse(partner_id).contact_ids:
                    arg[-1].append(contact.id)
            elif arg[0] == 'invoiced_customer_in_order_list':
                arg[0] = 'id'
                arg[1] = 'in'
                partner_rs = partner_obj.browse(arg[-1])
                if not partner_rs.is_company and partner_rs.parent_id:
                    partner_rs = partner_rs.parent_id

                arg[-1] = [
                    x.partner_type_id.id for x in partner_type_obj.search([(
                        'partner_type', '=',
                        'can_be_charged'), ('partner_id', '=', partner_rs.id)])
                    if x.partner_type_id
                ]
            elif arg[0] in ('cust_can_order', 'cust_can_be_charged'):
                if isinstance(arg[-1], list) and arg[-1][0]:
                    arg = ('id', '=', arg[-1][1])
                else:
                    match = True
                    args2.append((arg[0][5:], '=', True))
                    args2.append('|')
                    args2.append(('is_company', '=', False))
                    args2.append(('is_customer', '=', True))

            #On affiche les partenaires qui ont le partenaire passé dans le domaine dans leur liste de facturé
            elif arg[0] == 'order_customer_in_invoiced_list':
                arg[0] = 'id'
                arg[1] = 'in'
                partner_rs = partner_obj.browse(arg[-1])
                if not partner_rs.is_company and partner_rs.parent_id:
                    partner_rs = partner_rs.parent_id

                arg[-1] = [
                    x.partner_id.id
                    for x in partner_type_obj.search([('partner_type', '=',
                                                       'can_be_charged'),
                                                      ('partner_type_id', '=',
                                                       partner_rs.id)])
                    if x.partner_id
                ]
            #On affiche les partenaires livrables qui sont dans la liste du partenaire passé dans le domaine
            elif arg[0] == 'delivered_customer_in_order_list':
                arg[0] = 'id'
                arg[1] = 'in'
                partner_rs = partner_obj.browse(arg[-1])
                if not partner_rs.is_company and partner_rs.parent_id:
                    partner_rs = partner_rs.parent_id

                arg[-1] = [
                    x.partner_type_id.id for x in partner_type_obj.search([(
                        'partner_type', '=',
                        'can_be_delivered'), ('partner_id', '=',
                                              partner_rs.id)])
                    if x.partner_type_id
                ]
            #On affiche les partenaires payeurs qui sont dans la liste du partenaire passé dans le domaine
            elif arg[0] == 'paid_customer_in_order_list':
                arg[0] = 'id'
                arg[1] = 'in'
                partner_rs = partner_obj.browse(arg[-1])
                if not partner_rs.is_company and partner_rs.parent_id:
                    partner_rs = partner_rs.parent_id

                arg[-1] = [
                    x.partner_type_id.id for x in partner_type_obj.search([(
                        'partner_type', '=',
                        'can_paid'), ('partner_id', '=', partner_rs.id)])
                    if x.partner_type_id
                ]

            if not match:
                args2.append(arg)

        return args2

    @api.model
    def search(self, args=None, offset=0, limit=None, order=None, count=None):
        #Modification du search afin de n'afficher que les contacts inscrits dans la liste de contact
        args = args or []
        args_modified = self.compute_domain_args(args)
        return super(res_partner, self).search(args=args_modified,
                                               offset=offset,
                                               limit=limit,
                                               order=order,
                                               count=count)

    @api.model
    def read_group(self,
                   domain,
                   fields,
                   groupby,
                   offset=0,
                   limit=None,
                   orderby=False,
                   lazy=True):
        domain = self.compute_domain_args(domain)
        return super(res_partner, self).read_group(domain=domain,
                                                   fields=fields,
                                                   groupby=groupby,
                                                   offset=offset,
                                                   limit=limit,
                                                   orderby=orderby,
                                                   lazy=lazy)

    def modif_value_partner_type(self, modif_field):
        """"
            Mise à jour des champs dans les partenaires, selon les informations rentrées dans res.partner.type
            :param modif_field: Liste pour savoir quoi modifier: can_be_delivered, can_be_charged, can_paid, type_ids
            :type modif_field: char           
        """
        res = super(res_partner,
                    self).modif_value_partner_type(modif_field=modif_field)
        if modif_field == 'can_paid' and self.can_paid:
            request = """Select
                            partner_type_val.partner_id
                        From
                            (Select
                        
                                partner_id,
                                id
                            From
                                res_partner_type
                            Where
                                partner_type_id =  %s and
                                partner_type = 'can_paid') partner_type_val,
                            res_partner
                        Where
                            (res_partner.can_paid is null or res_partner.can_paid = false) and
                            partner_type_val.partner_id = res_partner.id and
                            partner_type_val.id = (Select id 
                                                   From res_partner_type 
                                                   Where partner_type = 'can_paid' and 
                                                         partner_id = partner_type_val.partner_id 
                                                   order by sequence asc limit 1) """ % (
                self.id)
            self.env.cr.execute(request)
            res_sql = self.env.cr.fetchall()
            if res_sql:
                partner_ids = [x[0] for x in res_sql]
                paid_vals = {}
                for x in self.paid_fields_partner():
                    if type(self[x]) is not int and type(
                            self[x]
                    ) is not str and type(self[x]) is not float and type(
                            self[x]) is not bool and type(
                                self[x]) is not unicode and self[x] != None:
                        if isinstance(
                            (self._fields[x]), fields.Many2many) or isinstance(
                                (self._fields[x]), fields.One2many):
                            paid_vals[x] = []
                            for i in self[x].ids:
                                paid_vals[x].append((4, i))
                        else:
                            paid_vals[x] = self[x].id
                    else:
                        paid_vals[x] = self[x]

                self.browse(partner_ids).write(paid_vals)

        elif modif_field == 'can_be_delivered' and self.can_be_delivered:
            request = """Select
                            partner_type_val.partner_id
                        From
                            (Select
                        
                                partner_id,
                                id
                            From
                                res_partner_type
                            Where
                                partner_type_id =  %s and
                                partner_type = 'can_be_delivered') partner_type_val,
                            res_partner
                        Where
                            (res_partner.can_be_delivered is null or res_partner.can_be_delivered = false) and
                            partner_type_val.partner_id = res_partner.id and
                            partner_type_val.id = (Select id 
                                                   From res_partner_type 
                                                   Where partner_type = 'can_be_delivered' and 
                                                         partner_id = partner_type_val.partner_id 
                                                   order by sequence asc limit 1) """ % (
                self.id)
            self.env.cr.execute(request)
            res_sql = self.env.cr.fetchall()
            if res_sql:
                partner_ids = [x[0] for x in res_sql]
                delivered_vals = {}
                for x in self.delivered_fields_partner():
                    if type(self[x]) is not int and type(
                            self[x]
                    ) is not str and type(self[x]) is not float and type(
                            self[x]) is not bool and type(
                                self[x]) is not unicode and self[x] != None:
                        if isinstance(
                            (self._fields[x]), fields.Many2many) or isinstance(
                                (self._fields[x]), fields.One2many):
                            delivered_vals[x] = []
                            for i in self[x].ids:
                                delivered_vals[x].append((4, i))
                        else:
                            delivered_vals[x] = self[x].id
                    else:
                        delivered_vals[x] = self[x]

                self.browse(partner_ids).write(delivered_vals)

        elif modif_field == 'can_be_charged' and self.can_be_charged:
            request = """Select
                            partner_type_val.partner_id
                        From
                            (Select
                        
                                partner_id,
                                id
                            From
                                res_partner_type
                            Where
                                partner_type_id =  %s and
                                partner_type = 'can_be_charged') partner_type_val,
                            res_partner
                        Where
                            (res_partner.can_be_charged is null or res_partner.can_be_charged = false) and
                            partner_type_val.partner_id = res_partner.id and
                            partner_type_val.id = (Select id 
                                                   From res_partner_type 
                                                   Where partner_type = 'can_be_charged' and 
                                                         partner_id = partner_type_val.partner_id 
                                                   order by sequence asc limit 1) """ % (
                self.id)
            self.env.cr.execute(request)
            res_sql = self.env.cr.fetchall()
            if res_sql:
                partner_ids = [x[0] for x in res_sql]
                invoiced_vals = {}
                for x in self.invoiced_fields_partner():
                    if type(self[x]) is not int and type(
                            self[x]
                    ) is not str and type(self[x]) is not float and type(
                            self[x]) is not bool and type(
                                self[x]) is not unicode and self[x] != None:
                        if isinstance(
                            (self._fields[x]), fields.Many2many) or isinstance(
                                (self._fields[x]), fields.One2many):
                            invoiced_vals[x] = []
                            for i in self[x].ids:
                                invoiced_vals[x].append((4, i))
                        else:
                            invoiced_vals[x] = self[x].id
                    else:
                        invoiced_vals[x] = self[x]

                self.browse(partner_ids).write(invoiced_vals)

        elif modif_field == 'type_ids':
            partner_type_obj = self.env['res.partner.type']
            if not self.can_paid:
                partner_type_rcs = partner_type_obj.search(
                    [('partner_type', '=', 'can_paid'),
                     ('partner_id', '=', self.id)],
                    order='sequence asc',
                    limit=1)
                if partner_type_rcs:
                    paid_vals = {}
                    for x in self.paid_fields_partner():
                        if type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not int and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not str and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not float and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not bool and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not unicode and partner_type_rcs.partner_type_id[
                                x] != None:
                            if isinstance(
                                (self._fields[x]),
                                    fields.Many2many) or isinstance(
                                        (self._fields[x]), fields.One2many):
                                paid_vals[x] = []
                                for i in partner_type_rcs.partner_type_id[
                                        x].ids:
                                    paid_vals[x].append((4, i))
                            else:
                                paid_vals[
                                    x] = partner_type_rcs.partner_type_id[x].id
                        else:
                            paid_vals[x] = partner_type_rcs.partner_type_id[x]

                    self.write(paid_vals)

            if not self.can_be_delivered:
                partner_type_rcs = partner_type_obj.search(
                    [('partner_type', '=', 'can_be_delivered'),
                     ('partner_id', '=', self.id)],
                    order='sequence asc',
                    limit=1)
                if partner_type_rcs:
                    delivered_vals = {}
                    for x in self.delivered_fields_partner():
                        if type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not int and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not str and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not float and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not bool and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not unicode and partner_type_rcs.partner_type_id[
                                x] != None:
                            if isinstance(
                                (self._fields[x]),
                                    fields.Many2many) or isinstance(
                                        (self._fields[x]), fields.One2many):
                                delivered_vals[x] = []
                                for i in partner_type_rcs.partner_type_id[
                                        x].ids:
                                    delivered_vals[x].append((4, i))
                            else:
                                delivered_vals[
                                    x] = partner_type_rcs.partner_type_id[x].id
                        else:
                            delivered_vals[
                                x] = partner_type_rcs.partner_type_id[x]

                    self.write(delivered_vals)

            if not self.can_be_charged:
                partner_type_rcs = partner_type_obj.search(
                    [('partner_type', '=', 'can_be_charged'),
                     ('partner_id', '=', self.id)],
                    order='sequence asc',
                    limit=1)
                if partner_type_rcs:
                    invoiced_vals = {}
                    for x in self.invoiced_fields_partner():
                        if type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not int and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not str and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not float and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not bool and type(
                                partner_type_rcs.partner_type_id[x]
                        ) is not unicode and partner_type_rcs.partner_type_id[
                                x] != None:
                            if isinstance(
                                (self._fields[x]),
                                    fields.Many2many) or isinstance(
                                        (self._fields[x]), fields.One2many):
                                invoiced_vals[x] = []
                                for i in partner_type_rcs.partner_type_id[
                                        x].ids:
                                    invoiced_vals[x].append((4, i))
                            else:
                                invoiced_vals[
                                    x] = partner_type_rcs.partner_type_id[x].id
                        else:
                            invoiced_vals[
                                x] = partner_type_rcs.partner_type_id[x]

                    self.write(invoiced_vals)

        return res
示例#27
0
class grpCajaChicaAccountVoucherWizard(models.TransientModel):
    _name = "grp.caja.chica.account.voucher.wizard"

    @api.model
    def fields_view_get(self,
                        view_id=None,
                        view_type='form',
                        context=None,
                        toolbar=False,
                        submenu=False):
        res = super(grpCajaChicaAccountVoucherWizard,
                    self).fields_view_get(view_id=view_id,
                                          view_type=view_type,
                                          context=context,
                                          toolbar=toolbar,
                                          submenu=submenu)
        doc = etree.XML(res['arch'])
        if self._context is not None and 'default_caja_chica_id' in self._context:
            caja_id = self._context['default_caja_chica_id']
            caja = self.env['grp.caja.chica.tesoreria'].search([('id', '=',
                                                                 caja_id)])
            account_vouchers = self.env['account.voucher'].search([
                ('state', '=', 'confirm'),
                ('id', 'not in',
                 caja.transaction_ids.mapped('voucher_id').ids),
                ('journal_id.caja_chica_t', '=', True),
                ('journal_id.operating_unit_id', 'in',
                 caja.box_id.operating_unit_ids.ids)
            ])
            if self.env.user.company_id.box_refund_in_selection == 'out_box':
                account_vouchers += self.env['account.voucher'].search([
                    ('state', '=', 'posted'),
                    ('id', 'not in',
                     caja.transaction_ids.mapped('voucher_id').ids),
                    ('journal_id.type', '=', 'sale'),
                    ('operating_unit_id', 'in',
                     caja.box_id.operating_unit_ids.ids), '|',
                    ('rendicion_viaticos_id', '!=', False),
                    ('rendicion_anticipos_id', '!=', False)
                ])
            for field in res['fields']:
                if field == 'account_voucher_ids':
                    res['fields'][field]['domain'] = [
                        ('id', 'in',
                         account_vouchers.filtered(lambda x: x.currency_id.id
                                                   == caja.currency.id).ids)
                    ]
            res['arch'] = etree.tostring(doc)
        return res

    payment_date = fields.Date('Fecha de pago',
                               default=lambda *a: fields.Date.today(),
                               required=True)
    entry_date = fields.Date('Fecha de asiento',
                             default=lambda *a: fields.Date.today(),
                             required=True)
    account_voucher_ids = fields.Many2many('account.voucher',
                                           string=u'Pago a proveedores')
    caja_chica_id = fields.Many2one('grp.caja.chica.tesoreria',
                                    string='Caja chica',
                                    ondelete='cascade')

    @api.onchange('payment_date')
    def _onchange_payment_date(self):
        self.entry_date = self.payment_date

    @api.multi
    def transfer_account_voucher(self):
        self.ensure_one()
        vouchers = self.mapped('account_voucher_ids')
        vouchers.write({
            'date': self.payment_date,
            'entry_date': self.entry_date
        })
        out_voucher_ids = vouchers.filtered(
            lambda x: not x.rendicion_viaticos_id and not x.
            rendicion_anticipos_id)
        in_voucher_ids = vouchers.filtered(
            lambda x: x.rendicion_viaticos_id or x.rendicion_anticipos_id)

        # out_voucher_ids.write({'date': self.payment_date, 'entry_date': self.entry_date})
        vouchers.with_context({'in_cashbox': True}).proforma_voucher()
        in_voucher_ids.write({'in_cashbox': True, 'state': 'pagado'})

        new_trasactions = [(0, 0, {
            'voucher_id': voucher.id,
            'ref': self.is_vale_viatico(voucher),
            'account_move_id': voucher.move_id.id,
            'date': self.payment_date,
            'entry_date': self.entry_date,
            'partner_id': voucher.partner_id.id,
            'amount': voucher.amount * -1
        }) for voucher in out_voucher_ids]
        new_trasactions.extend([(0, 0, {
            'voucher_id': voucher.id,
            'ref': self.is_vale_viatico(voucher),
            'account_move_id': voucher.move_id.id,
            'date': self.payment_date,
            'entry_date': self.entry_date,
            'partner_id': voucher.partner_id.id,
            'amount': voucher.amount
        }) for voucher in in_voucher_ids])

        self.caja_chica_id.write({'transaction_ids': new_trasactions})
        return True

    # TODO: C SPRING 12 GAP_301
    # RAGU: Seteando valores de ref para las lineas de la caja chica
    def is_vale_viatico(self, voucher):
        _vale_rec_name = False
        if voucher.rendicion_viaticos_id:
            _vale_rec_name = u'%s' % (
                voucher.rendicion_viaticos_id.name_get()[0][1])
        elif voucher.solicitud_viatico_id:
            _vale_rec_name = u'%s' % (
                voucher.solicitud_viatico_id.name_get()[0][1])
        elif voucher.rendicion_anticipos_id:
            _vale_rec_name = u'%s' % (
                voucher.rendicion_anticipos_id.name_get()[0][1])
        elif voucher.solicitud_anticipos_id:
            _vale_rec_name = u'%s' % (
                voucher.solicitud_anticipos_id.name_get()[0][1])

        if not _vale_rec_name:
            vale = self.env['grp.vale.caja'].search([
                ('aprobacion_pago_id', '=', voucher.invoice_id.id)
            ]) if voucher.invoice_id else False
            if vale:
                vale.write({'state': 'pagado'})
                _vale_rec_name = u'Vale(%s)' % (vale.number)
            s = set()
            for line_dr_id in voucher.line_dr_ids.filtered(
                    lambda x: x.reconcile):
                if line_dr_id.move_line_id.invoice.supplier_invoice_number:
                    s.add(line_dr_id.move_line_id.invoice.
                          supplier_invoice_number)
            s = list(s)
            if s:
                _vale_rec_name = u'Factura(%s)' % (', '.join(s))

        if not _vale_rec_name:
            _vale_rec_name = voucher.nro_documento and voucher.nro_documento.find(
                ', ') == -1 and voucher.nro_documento or voucher.number
        return _vale_rec_name
示例#28
0
class Currency_rate_update_service(models.Model):
    """Class keep services and currencies that
    have to be updated"""
    _name = "currency.rate.update.service"
    _description = "Currency Rate Update"

    @api.one
    @api.constrains('max_delta_days')
    def _check_max_delta_days(self):
        if self.max_delta_days < 0:
            raise exceptions.Warning(_('Max delta days must be >= 0'))

    @api.one
    @api.constrains('interval_number')
    def _check_interval_number(self):
        if self.interval_number < 0:
            raise exceptions.Warning(_('Interval number must be >= 0'))

    @api.onchange('interval_number')
    def _onchange_interval_number(self):
        if self.interval_number == 0:
            self.note = '%s Service deactivated. Currencies will no longer ' \
                        'be updated. \n%s' % (fields.Datetime.now(),
                                              self.note and self.note or '')

    @api.onchange('service')
    def _onchange_service(self):
        currency_list = ''
        if self.service:
            currencies = []
            currency_list = supported_currency_array
            company_id = False
            if self.company_id.multi_company_currency_enable:
                company_id = self.company_id.id
            currency_list = supported_currecies[self.service]
            if company_id:
                currencies = self.env['res.currency'].search([
                    ('name', 'in', currency_list), '|',
                    ('company_id', '=', company_id), ('company_id', '=', False)
                ])
            else:
                currencies = self.env['res.currency'].search([
                    ('name', 'in', currency_list), ('company_id', '=', False)
                ])
            self.currency_list = [(6, 0, [curr.id for curr in currencies])]
#            _logger.info("Self currency list %s:" % self.currency_list)
#            _logger.info("Company currency list %s:" % currencies)

# List of webservicies the value sould be a class name

    service = fields.Selection(
        [
            ('CH_ADMIN_getter', 'Admin.ch'),
            ('ECB_getter', 'European Central Bank'),
            ('YAHOO_getter', 'Yahoo Finance'),
            # Added for polish rates
            ('PL_NBP_getter', 'National Bank of Poland'),
            # Added for mexican rates
            ('MX_BdM_getter', 'Bank of Mexico'),
            # Bank of Canada is using RSS-CB
            # http://www.cbwiki.net/wiki/index.php/Specification_1.1
            # This RSS format is used by other national banks
            #  (Thailand, Malaysia, Mexico...)
            ('CA_BOC_getter', 'Bank of Canada - noon rates'),
            # Added for romanian rates
            ('RO_BNR_getter', 'National Bank of Romania'),
            # Added for bulgarian rates of central, statiscs (customs) and buy and sell from two bank
            ('BG_CUSTOMS_getter', 'Bulgarian customs rate for taxes'),
            ('BG_SIBANK_getter',
             'bulgarian SiBank bay and sell currency rates'),
            ('BG_UNICRDT_getter',
             'bulgarian Unicredit Bulbank bay and sell currency rates'),
        ],
        string="Webservice to use",
        required=True)
    # List of currencies available on webservice
    currency_list = fields.Many2many('res.currency',
                                     'res_currency_update_avail_rel',
                                     'service_id',
                                     'currency_id',
                                     string='Currencies available')
    # List of currency to update
    currency_to_update = fields.Many2many('res.currency',
                                          'res_currency_auto_update_rel',
                                          'service_id',
                                          'currency_id',
                                          string='Currencies to update with '
                                          'this service')
    # Link with company
    company_id = fields.Many2one(
        'res.company',
        'Company',
        default=lambda self: self.env['res.company']._company_default_get(
            'currency.rate.update.service'))
    # Note fileds that will be used as a logger
    note = fields.Text('Update logs')
    max_delta_days = fields.Integer(
        string='Max delta days',
        default=4,
        required=True,
        help="If the time delta between the rate date given by the "
        "webservice and the current date exceeds this value, "
        "then the currency rate is not updated in OpenERP.")
    interval_type = fields.Selection([('days', 'Day(s)'), ('weeks', 'Week(s)'),
                                      ('months', 'Month(s)')],
                                     string='Currency update frequency',
                                     default='days')
    interval_number = fields.Integer(string='Frequency', default=1)
    next_run = fields.Date(string='Next run on', default=fields.Date.today())

    _sql_constraints = [('curr_service_unique', 'unique (service, company_id)',
                         _('You can use a service only one time per '
                           'company !'))]

    @api.one
    def refresh_currency(self):
        """Refresh the currencies rates !!for all companies now"""
        _logger.info(
            'Starting to refresh currencies with service %s (company: %s)',
            self.service, self.company_id.name)
        factory = Currency_getter_factory()
        _logger.info("Factory %s:" % factory)
        curr_obj = self.env['res.currency']
        rate_obj = self.env['res.currency.rate']
        company = self.company_id
        # The multi company currency can be set or no so we handle
        # The two case
        if company.auto_currency_up:
            main_currency = curr_obj.search([('base', '=', True),
                                             ('company_id', '=', company.id)],
                                            limit=1)
            if not main_currency:
                # If we can not find a base currency for this company
                # we look for one with no company set
                main_currency = curr_obj.search([('base', '=', True),
                                                 ('company_id', '=', False)],
                                                limit=1)
            if not main_currency:
                raise exceptions.Warning(_('There is no base currency set!'))
            if main_currency.rate != 1:
                raise exceptions.Warning(
                    _('Base currency rate should '
                      'be 1.00!'))
            note = self.note or ''
            try:
                # We initalize the class that will handle the request
                # and return a dict of rate
                getter = factory.register(self.service)
                #self.init_updated_currency()
                _logger.info("Execute %s: -> %s" %
                             (getter, self.currency_to_update))
                curr_to_fetch = map(lambda x: x.name, self.currency_to_update)
                res, log_info = getter.get_updated_currency(
                    curr_to_fetch, main_currency.name, self.max_delta_days)
                rate_name = \
                    fields.Datetime.to_string(datetime.utcnow().replace(
                        hour=0, minute=0, second=0, microsecond=0))
                for curr in self.currency_to_update:
                    if curr.id == main_currency.id:
                        continue
                    do_create = True
                    #                    _logger.info("res curr %s" % res)
                    for rate in curr.rate_ids:
                        _logger.info(
                            "to update: %s:%s from date: %s to date: %s->%s" %
                            (curr.id, rate['currency_id'], rate_name,
                             rate.name, rate))
                        if rate.name == rate_name and rate.currency_id == curr.id:
                            vals = {
                                'rate':
                                res['rate'] and res['rate'][curr.name] or 0,
                                'rate_buy':
                                res['rate_buy'] and res['rate_buy'][curr.name]
                                or 0,
                                'rate_sell':
                                res['rate_sell']
                                and res['rate_sell'][curr.name] or 0,
                                'rate_statistics':
                                res['rate_statistics']
                                and res['rate_statistics'][curr.name] or 0,
                            }
                            rate_obj.write(vals)
                            _logger.info(
                                'Updated currency %s via service %s on date %s',
                                curr.name, self.service, rate_name)
                            do_create = False
                            break
                        else:
                            vals = {
                                'currency_id':
                                curr.id,
                                'rate':
                                res['rate'] and res['rate'][curr.name] or 0,
                                'rate_buy':
                                res['rate_buy'] and res['rate_buy'][curr.name]
                                or 0,
                                'rate_sell':
                                res['rate_sell']
                                and res['rate_sell'][curr.name] or 0,
                                'rate_statistics':
                                res['rate_statistics']
                                and res['rate_statistics'][curr.name] or 0,
                                'name':
                                rate_name
                            }
                            do_create = True
                            break
                    if do_create:
                        rate_obj.create(vals)
                        _logger.info(
                            'Updated add currency %s via service %s on date %s',
                            curr.name, self.service, rate_name)

                # Show the most recent note at the top
                msg = '%s \n%s currency updated. %s' % (
                    log_info or '', fields.Datetime.to_string(
                        datetime.today()), note)
                self.write({'note': msg})
            except Exception as exc:
                error_msg = '\n%s ERROR : %s %s' % (fields.Datetime.to_string(
                    datetime.today()), repr(exc), note)
                _logger.error(repr(exc))
                self.write({'note': error_msg})
            if self._context.get('cron', False):
                midnight = time(0, 0)
                next_run = (datetime.combine(
                    fields.Date.from_string(self.next_run), midnight) +
                            _intervalTypes[str(self.interval_type)](
                                self.interval_number)).date()
                self.next_run = next_run

    @api.multi
    def run_currency_update(self):
        # Update currency at the given frequence
        #        _logger.info('Check for refresh %s' % fields.Date.today())
        services = self.search([('next_run', '<=', fields.Date.today())])
        services.with_context(cron=True).refresh_currency()

    @api.model
    def _run_currency_update(self):
        _logger.info('Starting the currency rate update cron')
        self.run_currency_update()
        _logger.info('End of the currency rate update cron')
示例#29
0
class Session(models.Model):
    _name = 'openacademy.session'

    name = fields.Char(required=True)
    start_date = fields.Date(default=fields.Date.today)
    duration = fields.Float(digits=(6, 2), help="Duration in days")
    seats = fields.Integer(string="Number of seats")
    active = fields.Boolean(default=True)
    instructor_id = fields.Many2one('res.partner', string="Instructor",
        domain=['|', ('instructor', '=', True),
                     ('category_id.name', 'ilike', "Teacher")])
    course_id = fields.Many2one('openacademy.course',
        ondelete='cascade', string="Course", required=True)
    attendee_ids = fields.Many2many('res.partner', string="Attendees")
    taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')
    end_date = fields.Date(store=True, compute='_get_end_date',
        inverse='_set_end_date')
    hours = fields.Float(string="Duration in hours",
                         compute='_get_hours', inverse='_set_hours')
    attendees_count = fields.Integer(compute='_get_attendees_count',
                                     store=True)
    color = fields.Integer()
    state = fields.Selection([
        ('draft', "Draft"),
        ('confirmed', "Confirmed"),
        ('done', "Done"),
    ])

    @api.multi
    def action_draft(self):
        self.state = 'draft'

    @api.multi
    def action_confirm(self):
        self.state = 'confirmed'

    @api.multi
    def action_done(self):
        self.state = 'done'

    @api.depends('attendee_ids')
    def _get_attendees_count(self):
        for r in self:
            r.attendees_count = len(r.attendee_ids)

    @api.depends('duration')
    def _get_hours(self):
        for r in self:
            r.hours = r.duration * 24

    def _set_hours(self):
        for r in self:
            r.duration = r.hours / 24

    @api.depends('start_date', 'duration')
    def _get_end_date(self):
        for r in self:
            if not (r.start_date and r.duration):
                r.end_date = r.start_date
                continue
            start = fields.Datetime.from_string(r.start_date)
            duration = timedelta(days=r.duration, seconds=-1)
            r.end_date = start + duration

    def _set_end_date(self):
        for r in self:
            if not (r.start_date and r.end_date):
                continue
            start_date = fields.Datetime.from_string(r.start_date)
            end_date = fields.Datetime.from_string(r.end_date)
            r.duration = (end_date - start_date).days + 1

    @api.depends('seats', 'attendee_ids')
    def _taken_seats(self):
        for r in self:
            if not r.seats:
                r.taken_seats = 0.0
            else:
                r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats

    @api.onchange('seats', 'attendee_ids')
    def _verify_valid_seats(self):
        if self.seats < 0:
            return {
                'warning': {
                    'title': "Incorrect 'seats' value",
                    'message': "The number of available seats may not be negative",
                },
            }
        if self.seats < len(self.attendee_ids):
            return {
                'warning': {
                    'title': "Too many attendees",
                    'message': "Increase seats or remove excess attendees",
                },
            }

    @api.constrains('instructor_id', 'attendee_ids')
    def _check_instructor_not_in_attendees(self):
        for r in self:
            if r.instructor_id and r.instructor_id in r.attendee_ids:
                raise exceptions.ValidationError("A session's instructor can't be an attendee")
示例#30
0
class advance_rm_material(models.Model):
    _name = 'advance.rm.material'
    _description = "Advance Raw Material Plan"
    _inherit = ['mail.thread', 'ir.needaction_mixin']
    _order = 'create_date desc'

    @api.multi
    def button_dummy(self):
        return True

    @api.multi
    def generate_po(self):
        # supplier_dict = {}
        product_list = []
        po_ids = []
        po_raise_list = []
        supplier_name = False
        for record in self.advance_rawmaterial_one2many:
            if record.po_raise == True:
                po_raise_list.append(record)
        if po_raise_list:
            supplier_dict = {}
            for po in po_raise_list:

                product_product = self.env['product.product'].search([
                    ('product_tmpl_id', '=', po.product_id.id)
                ])

                if po.supplier_id.id in supplier_dict:
                    supplier_dict[po.supplier_id.id].append(
                        (product_product, po.po_qty, po.current_price))
                else:
                    supplier_dict[po.supplier_id.id] = [
                        (product_product, po.po_qty, po.current_price)
                    ]
        else:
            # print "Hai hi nahi koi PO raise"
            raise UserError('No PO raise is found ')
        for supplier_name, product_name in supplier_dict.iteritems():
            if supplier_name:

                vals = {
                    'partner_id': supplier_name,
                    'type_order': 'purchase',
                    'date_order': self.date,
                    # 'date_planned':self.date,
                    # 'currency_id':'INR'
                    'advance_rm_material_id': self.id,
                    'origin': self.fg_plan.name + " / " + self.name
                }
                purchase_order = self.env['purchase.order'].create(vals)
                po_ids.append(purchase_order.id)
                for products in product_name:
                    vals_line = {
                        'product_id':
                        products[0].id,
                        # 'tax_id':[(4,products[0].supplier_taxes_id.id)],
                        'taxes_id':
                        [(4, x.id) for x in products[0].supplier_taxes_id],
                        'date_planned':
                        self.date,
                        'order_id':
                        purchase_order.id,
                        'product_qty':
                        products[1],
                        'name':
                        products[0].name,
                        'product_uom':
                        products[0].uom_po_id.id,
                        'price_unit':
                        products[2] if
                        (products[2] > 0) else products[0].standard_price,
                    }
                    self.env['purchase.order.line'].create(vals_line)

            else:
                raise UserError('Please Select Supplier For all the Products')

        imd = self.env['ir.model.data']
        action = self.env.ref('purchase.purchase_rfq')
        result = action.read([])[0]
        result['domain'] = [('id', 'in', po_ids)]
        self.state = 'done'
        # print Error
        return result

    @api.multi
    def count_docs(self):
        po_ids = self.env['purchase.order'].search([("advance_rm_material_id",
                                                     "=", self.id)])
        if len(po_ids):
            self.attach_doc_count = len(po_ids) or 0

    @api.multi
    def get_attached_docs(self):
        po_ids = self.env['purchase.order'].search([("advance_rm_material_id",
                                                     "=", self.id)])
        imd = self.env['ir.model.data']
        action = imd.xmlid_to_object('purchase.purchase_rfq')
        list_view_id = imd.xmlid_to_res_id('purchase.purchase_order_tree')
        form_view_id = imd.xmlid_to_res_id('purchase.purchase_order_form')
        result = {
            'name':
            action.name,
            'help':
            action.help,
            'type':
            action.type,
            'views': [[list_view_id, 'tree'], [form_view_id, 'form'],
                      [False, 'graph'], [False, 'kanban'], [False, 'calendar'],
                      [False, 'pivot']],
            'target':
            action.target,
            'context':
            action.context,
            'res_model':
            action.res_model,
        }
        if len(po_ids) > 1:
            result['domain'] = "[('id','in',%s)]" % po_ids.ids
        elif len(po_ids) == 1:
            result['views'] = [(form_view_id, 'form')]
            result['res_id'] = po_ids.ids[0]
        else:
            result = {'type': 'ir.actions.act_window_close'}
        return result

    name = fields.Char(string="Plan No.", track_visibility='always')
    fg_plan = fields.Many2one('advance.fg.material', string='FG Plan No.')
    date = fields.Date(string="Date")
    user_id = fields.Many2one('res.users',
                              string='User',
                              default=lambda self: self._uid,
                              track_visibility='always')
    advance_rawmaterial_one2many = fields.One2many(
        'advance.rawmaterial',
        'advance_rm_material_id',
        string="Advance Raw Material")
    # purchase_order_id = fields.Many2one('purchase.order', track_visibility='always' )
    purchase_order_ids = fields.Many2many("purchase.order",
                                          string='Purchases',
                                          compute="get_attached_docs",
                                          readonly=True,
                                          copy=False)
    attach_doc_count = fields.Integer(string="Number of documents attached",
                                      compute='count_docs')

    average_forecast = fields.Integer(string="Average Forecast", required=True)

    months = fields.Selection([
        ('three', 'Three'),
        ('six', 'Six'),
        ('year', 'Year'),
    ],
                              string='Months',
                              track_visibility='always',
                              default='three')

    state = fields.Selection([
        ('draft', 'Draft'),
        ('done', 'Done'),
        ('cancel', 'Cancelled'),
    ],
                             string='Status',
                             readonly=True,
                             copy=False,
                             index=True,
                             track_visibility='always',
                             default='draft')

    @api.model
    def create(self, vals):
        vals['name'] = self.env['ir.sequence'].next_by_code(
            'advance.rm.material')
        # vals['state'] = 'done'
        result = super(advance_rm_material, self).create(vals)
        if result.fg_plan:
            result.fg_plan.state = result.state
            result.fg_plan.advance_rm_material_id = result.id
        return result

    @api.multi
    def write(self, values):
        result = super(advance_rm_material, self).write(values)
        if self.fg_plan:
            self.fg_plan.state = self.state
            self.fg_plan.advance_rm_material_id = self.id
        return result

    @api.multi
    def name_get(self):
        result = []
        for ai in self:
            b = datetime.strptime(ai.date, '%Y-%m-%d').strftime('%d %B %Y')
            name = str(ai.name) + ' ( ' + b + ' )'
            result.append((ai.id, name))
        return result

    @api.constrains('average_forecast')
    def constraints_check(self):
        if self.average_forecast == 0:
            print "OOOOOOOOOOOOOOOOOOOOOOO Please enter Average Forecast"
            raise UserError("Please enter Average Forecast")