Пример #1
0
 def _update_models(self, cr, models={}):
     if not models:
         checklist_ids = self.search(cr, 1, [])
         models = dict([(checklist['model_id'][0], {'checklist_id': checklist['id'], 'active_field': checklist['active_field']})
                        for checklist in self.read(cr, 1, checklist_ids, ['model_id', 'active_field'])])
     for model in self.pool.get('ir.model').read(cr, 1, models.keys(), ['model']):
         if self.pool.get(model['model']):
             model_columns = self.pool.get(model['model'])._columns
             checklist_id = models[model['id']] and models[model['id']].get('checklist_id', False)
             if checklist_id:
                 model_columns.update({
                     'checklist_task_instance_ids': fields.function(self._get_checklist_task_instances, type='one2many',
                                                                    relation='checklist.task.instance', string='Checklist Task Instances',
                                                                    store=False),
                     'total_progress_rate': fields.float('Progress Rate', digits=(16, 2)),
                 })
                 columns_to_add = {'total_progress_rate': 'NUMERIC(16,2)'}
                 if models[model['id']].get('active_field', False):
                     if 'active' not in model_columns or model_columns['active']._type != 'boolean':
                         model_columns.update({'active': fields.boolean('Active')})
                     model_columns.update({'total_progress_rate_mandatory': fields.float('Mandatory Progress Rate', digits=(16, 2))})
                     columns_to_add.update({'active': 'BOOLEAN', 'total_progress_rate_mandatory': 'NUMERIC(16,2)'})
                 for column in columns_to_add:
                     cr.execute("""SELECT c.relname FROM pg_class c, pg_attribute a
                                   WHERE c.relname=%s AND a.attname=%s AND c.oid=a.attrelid""", (model['model'].replace('.', '_'), column))
                     if not cr.rowcount:
                         cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (model['model'].replace('.', '_'), column, columns_to_add[column]))
                         cr.commit()
             else:
                 if 'checklist_task_instance_ids' in model_columns:
                     del model_columns['checklist_task_instance_ids']
                 if 'total_progress_rate' in model_columns:
                     del model_columns['total_progress_rate']
     return self._update_checklists_cache(cr)
Пример #2
0
 def __init__(self, pool, cr):
     cr.execute("select id,name from stock_warehouse")
     model_obj = pool.get("ir.model.data")
     view_obj = pool.get("ir.ui.view")
     tree_arch = '<tree string="Productos por almacen">\n'
     tree_arch += '<field name="name"/>\n'
     tree_arch += '<field name="default_code"/>\n'
     tree_arch += '<field name="list_price"/>\n'
     tree_arch += '<field name="standard_price"/>\n'
     unsorted_warehouse=[]
     for row in cr.fetchall():
         field_name = "qty_warehouse_%s"%row[0]
         self._columns[field_name] = fields.function(get_qty_warehouse, type="float", method=False, string=row[1], multi="qtys")
         unsorted_warehouse.append(['<field name="%s"/>\n'%field_name,row[1]])
     
     sorted_warehouse=sorted(unsorted_warehouse,key=itemgetter(1))
     ordered_fields=""
     for item in sorted_warehouse:
         ordered_fields+=item[0]
     tree_arch += ordered_fields+'</tree>'
     res = super(reporte_almacenes, self).__init__(pool, cr)
     try:
         view_rec = model_obj.get_object_reference(cr, 1, 'reporte_almacenes', 'reporte_view_tree')
         view_id_tree = view_rec and view_rec[1] or False
         if view_id_tree:
             view_obj.write(cr, 1, view_id_tree, {'arch': tree_arch})
     except ValueError:
         pass
     return res    
Пример #3
0
 def _report_content_txt_inv(self, cr, uid, id, name, value, arg, context=None):
 self.write(cr,uid,id,{'report_rml_content':str(value)},context=context)
 
 
 _name = 'ir.actions.report.xml'
 _inherit = 'ir.actions.report.xml'
 _columns = {
     'report_rml_content_txt': fields.function(_report_content_txt, fnct_inv=_report_content_txt_inv, method=True, type='text', string='RML text content'),
     
 }
Пример #4
0
    def _get_alias_domain(self, cr, uid, ids, name, args, context=None):

        if context is None:
            context = {}        
        userid = context.get('uid',uid)
        ir_config_parameter = self.pool.get("ir.config_parameter")
        #domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context)
        domain = self.pool.get('res.users').browse(cr, uid, userid, context=context).company_id.email_domain       
        print 'wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww'
        print domain
        return dict.fromkeys(ids, domain or "")

        _columns = {

        'alias_domain': fields.function(_get_alias_domain, string="Alias domain", type='char', size=None),
        }
Пример #5
0
    def __init__(self, pool, cr):
        """ Dynamically add columns."""

        super(report_prompt_class, self).__init__(pool, cr)

        for counter in range(0, MAX_PARAMS):
            field_name = PARAM_XXX_STRING_VALUE % counter
            self._columns[field_name] = fields.char('String Value', size=64)
            field_name = PARAM_XXX_BOOLEAN_VALUE % counter
            self._columns[field_name] = fields.boolean('Boolean Value')
            field_name = PARAM_XXX_INTEGER_VALUE % counter
            self._columns[field_name] = fields.integer('Integer Value')
            field_name = PARAM_XXX_NUMBER_VALUE % counter
            self._columns[field_name] = fields.float('Number Value')
            field_name = PARAM_XXX_DATE_VALUE % counter
            self._columns[field_name] = fields.date('Date Value')
            field_name = PARAM_XXX_TIME_VALUE % counter
            self._columns[field_name] = fields.datetime('Time Value')
            field_name = PARAM_XXX_2M_VALUE % counter
            self._columns[field_name] = fields.function(self._multi_select_values.im_func,
                                                        arg={"entry_num": counter},
                                                        fnct_inv=self._multi_select_values_store.im_func,
                                                        fnct_inv_arg={"entry_num": counter},
                                                        method=False, type='many2many', relation='ir.actions.report.multivalues.promptwizard', string='Multi-Select')
Пример #6
0
        ###Function that will update the cron
        ###freqeuence
        self.pool.get("currency.rate.update").save_cron(cr, uid, {"interval_type": interval})
        compagnies = self.search(cr, uid, [])
        for comp in compagnies:
            self.write(cr, uid, comp, {"interval_type": interval})
        return {}

    _inherit = "res.company"
    _columns = {
        ### activate the currency update
        "auto_currency_up": fields.boolean("Automatical update of the currency this company"),
        "services_to_use": fields.one2many("currency.rate.update.service", "company_id", "Currency update services"),
        ###predifine cron frequence
        "interval_type": fields.selection(
            [("days", "Day(s)"), ("weeks", "Week(s)"), ("months", "Month(s)")],
            "Currency update frequence",
            help="""changing this value will
                                                 also affect other compagnies""",
        ),
        ###function field that allows to know the
        ###mutli company currency implementation
        "multi_company_currency_enable": fields.function(
            _multi_curr_enable,
            method=True,
            type="boolean",
            string="Multi company currency",
            help="if this case is not check you can" + " not set currency is active on two company",
        ),
    }
Пример #7
0
class purchase_order_line(osv.osv):
    _inherit = 'purchase.order.line'

    def compute_list(self, total_paid, quantities, prices, ids):
        new_prices = [Decimal(str(p)) for p in prices]
        new_quantities = [Decimal(str(qty)) for qty in quantities]
        totals_ary = [p * qty for p, qty in zip(new_quantities, new_prices)]
        total = sum(totals_ary)

        total_paid = Decimal(str(total_paid))

        # totals + importation expenses
        total_importation = [n + total_paid * (n / total) for n in totals_ary]

        # prices + importantion expenses
        expenses = [
            imp / qty for qty, imp in zip(new_quantities, total_importation)
        ]

        ret = [round(float(expend), 2) for expend in expenses]

        return [{'id': t[0], 'price': t[1]} for t in zip(ids, ret)]

    def extract_lists(self, products):
        ids = []
        prices = []
        quantities = []

        for product_info in products:
            ids.append(product_info['id'])
            prices.append(product_info['price'])
            quantities.append(product_info['qty'])

        return {'ids': ids, 'prices': prices, 'quantities': quantities}

    def _amount_line_liquidation(self, cr, uid, ids, prop, arg, context=None):
        order = self.browse(cr, uid, ids, context=context)[0]
        response = {}
        if order.order_id.importation:

            res_list = []
            rate = order.order_id.custom_rate
            lines = self.browse(cr, uid, ids, context=context)
            for line in lines:
                if line.price_subtotal <= 0:
                    raise osv.except_osv(
                        'Alerta!', "No puede agragar productos con valor cero")
                elif rate < 0:
                    raise osv.except_osv(
                        'Alerta!',
                        "Debe de expecificar la taza de la planilla de importacion"
                    )
                elif order.order_id.dop_total_cost <= 0:
                    raise osv.except_osv(
                        'Alerta!',
                        "Debe de expecificar el total de los gastos en pesos para esta importacion"
                    )
                elif order.order_id.usd_total_cost <= 0:
                    raise osv.except_osv(
                        'Alerta!',
                        "Debe de expecificar el total de los gastos en dolares para esta importacion"
                    )

                res = {}
                res["id"] = line.id
                res["qty"] = line.product_qty
                res["price"] = line.price_subtotal / line.product_qty
                res_list.append(res)

            lista = self.extract_lists(res_list)
            total_importacion = (order.order_id.dop_total_cost /
                                 rate) + order.order_id.usd_total_cost
            rets = self.compute_list(total_importacion, lista['quantities'],
                                     lista['prices'], lista['ids'])
            for ret in rets:
                response[ret["id"]] = ret["price"]
            return response
        return {}

    _columns = {
        'price_unit_pesos':
        fields.function(_amount_line_liquidation,
                        string='Cost unit (USD)',
                        digits_compute=dp.get_precision('Account'))
    }
Пример #8
0
class IslrWhDocInvoices(osv.osv):
    _inherit = 'islr.wh.doc.invoices'

    def _amount_all(self, cr, uid, ids, fieldname, args, context=None):
        """ Return all amount relating to the invoices lines
            _13DIC2016_rsosa: changes..
        """
        res = {}
        ut_obj = self.pool.get('l10n.ut')
        for ret_line in self.browse(cr, uid, ids, context):
            flag = ret_line.invoice_id.flag_currency or False
            f_xc = ut_obj.sxc(cr, uid,
                              ret_line.invoice_id.company_id.currency_id.id,
                              ret_line.invoice_id.currency_id.id,
                              ret_line.islr_wh_doc_id.date_uid)
            res[ret_line.id] = {
                'amount_islr_ret': 0.0,
                'base_ret': 0.0,
                'currency_amount_islr_ret': 0.0,
                'currency_base_ret': 0.0,
            }
            for line in ret_line.iwdl_ids:
                res[ret_line.id]['amount_islr_ret'] += line.amount
                res[ret_line.id]['base_ret'] += line.base_amount
                #_14DIC2016_rsosa:
                res[ret_line.id]['currency_amount_islr_ret'] += flag and round((line.amount / line.invoice_id.res_currency_rate),4) \
                                                                or f_xc(line.amount)
                if flag:
                    res[ret_line.id][
                        'currency_base_ret'] = line.invoice_id.amount_untaxed
                else:
                    res[ret_line.id]['currency_base_ret'] += f_xc(
                        line.base_amount)

        return res

    #_14DIC2016_rsosa: Se agrega la definicion de estos campos funcionales no para cambiarlos, sino para poder sobreescribir el metodo
    #                          que los alimenta (_amount_all).
    _columns = {
        'amount_islr_ret':
        fields.function(_amount_all,
                        method=True,
                        digits=(16, 2),
                        string='Withheld Amount',
                        multi='all',
                        help="Amount withheld from the base amount"),
        'base_ret':
        fields.function(
            _amount_all,
            method=True,
            digits=(16, 2),
            string='Base Amount',
            multi='all',
            help="Amount where a withholding is going to be compute from"),
        'currency_amount_islr_ret':
        fields.function(_amount_all,
                        method=True,
                        digits=(16, 2),
                        string='Foreign Currency Withheld Amount',
                        multi='all',
                        help="Amount withheld from the base amount"),
        'currency_base_ret':
        fields.function(
            _amount_all,
            method=True,
            digits=(16, 2),
            string='Foreign Currency Base Amount',
            multi='all',
            help="Amount where a withholding is going to be compute from"),
    }

    def _get_wh(self, cr, uid, ids, concept_id, context=None):
        """ Return a dictionary containing all the values of the retention of an
        invoice line.
        @param concept_id: Withholding reason
        """
        # TODO: Change the signature of this method
        # This record already has the concept_id built-in
        context = context or {}
        ids = isinstance(ids, (int, long)) and [ids] or ids
        ixwl_obj = self.pool.get('islr.xml.wh.line')
        iwdl_obj = self.pool.get('islr.wh.doc.line')
        iwdl_brw = iwdl_obj.browse(cr, uid, ids[0], context=context)

        ut_date = iwdl_brw.islr_wh_doc_id.date_uid
        ut_obj = self.pool.get('l10n.ut')
        money2ut = ut_obj.compute
        ut2money = ut_obj.compute_ut_to_money

        vendor, buyer, wh_agent = self._get_partners(cr, uid,
                                                     iwdl_brw.invoice_id)
        wh_agent = wh_agent
        apply_income = not vendor.islr_exempt
        residence = self._get_residence(cr, uid, vendor, buyer)
        nature = self._get_nature(cr, uid, vendor)

        concept_id = iwdl_brw.concept_id.id
        # rate_base,rate_minimum,rate_wh_perc,rate_subtract,rate_code,rate_id,
        # rate_name
        # Add a Key in context to store date of ret fot U.T. value
        # determination
        # TODO: Future me, this context update need to be checked with the
        # other date in the withholding in order to take into account the
        # customer income withholding.
        context.update({
            'wh_islr_date_ret':
            iwdl_brw.islr_wh_doc_id.date_uid
            or iwdl_brw.islr_wh_doc_id.date_ret or False
        })
        base = 0
        wh_concept = 0.0

        # Using a clousure to make this call shorter
        f_xc = ut_obj.sxc(cr, uid, iwdl_brw.invoice_id.currency_id.id,
                          iwdl_brw.invoice_id.company_id.currency_id.id,
                          iwdl_brw.invoice_id.date_invoice)

        if iwdl_brw.invoice_id.type in ('in_invoice', 'in_refund'):
            for line in iwdl_brw.xml_ids:
                if line.account_invoice_id.type == 'in_invoice' and line.account_invoice_id.flag_currency:
                    rate_c = line.account_invoice_id.res_currency_rate
                    #base += f_xc(line.account_invoice_line_id.price_subtotal)
                    base += round(
                        (line.account_invoice_line_id.price_subtotal * rate_c),
                        4)
                else:
                    base += f_xc(line.account_invoice_line_id.price_subtotal)

            # rate_base, rate_minimum, rate_wh_perc, rate_subtract, rate_code,
            # rate_id, rate_name, rate2 = self._get_rate(
            #    cr, uid, ail_brw.concept_id.id, residence, nature, base=base,
            #    inv_brw=ail_brw.invoice_id, context=context)
            rate_tuple = self._get_rate(cr,
                                        uid,
                                        concept_id,
                                        residence,
                                        nature,
                                        base=base,
                                        inv_brw=iwdl_brw.invoice_id,
                                        context=context)

            if rate_tuple[7]:
                apply_income = True
                residual_ut = ((rate_tuple[0] / 100.0) *
                               (rate_tuple[2] / 100.0) *
                               rate_tuple[7]['cumulative_base_ut'])
                residual_ut -= rate_tuple[7]['cumulative_tax_ut']
                residual_ut -= rate_tuple[7]['subtrahend']
            else:
                apply_income = (apply_income and
                                base >= rate_tuple[0] * rate_tuple[1] / 100.0)
            wh = 0.0
            subtract = apply_income and rate_tuple[3] or 0.0
            subtract_write = 0.0
            sb_concept = subtract
            for line in iwdl_brw.xml_ids:
                if line.account_invoice_id.type == 'in_invoice' and line.account_invoice_id.flag_currency:
                    #_13DIC2016_rsosa:
                    rate_c = line.account_invoice_id.res_currency_rate
                    #base_line = f_xc(line.account_invoice_line_id.price_subtotal)
                    base_line = round(
                        (line.account_invoice_line_id.price_subtotal * rate_c),
                        4)
                else:
                    base_line = f_xc(
                        line.account_invoice_line_id.price_subtotal)
                base_line_ut = money2ut(cr, uid, base_line, ut_date)
                values = {}
                if apply_income and not rate_tuple[7]:
                    wh_calc = ((rate_tuple[0] / 100.0) *
                               (rate_tuple[2] / 100.0) * base_line)
                    if subtract >= wh_calc:
                        wh = 0.0
                        subtract -= wh_calc
                    else:
                        wh = wh_calc - subtract
                        subtract_write = subtract
                        subtract = 0.0
                    values = {
                        'wh': wh,
                        'raw_tax_ut': money2ut(cr, uid, wh, ut_date),
                        'sustract': subtract or subtract_write,
                    }
                elif apply_income and rate_tuple[7]:
                    tax_line_ut = (base_line_ut * (rate_tuple[0] / 100.0) *
                                   (rate_tuple[2] / 100.0))
                    if residual_ut >= tax_line_ut:
                        wh_ut = 0.0
                        residual_ut -= tax_line_ut
                    else:
                        wh_ut = tax_line_ut + residual_ut
                        subtract_write_ut = residual_ut
                        residual_ut = 0.0
                    wh = ut2money(cr, uid, wh_ut, ut_date)
                    values = {
                        'wh':
                        wh,
                        'raw_tax_ut':
                        wh_ut,
                        'sustract':
                        ut2money(cr, uid, residual_ut or subtract_write_ut,
                                 ut_date),
                    }
                values.update({
                    'base': base_line * (rate_tuple[0] / 100.0),
                    'raw_base_ut': base_line_ut,
                    'rate_id': rate_tuple[5],
                    'porcent_rete': rate_tuple[2],
                    'concept_code': rate_tuple[4],
                })
                ixwl_obj.write(cr, uid, line.id, values, context=context)
                wh_concept += wh
        else:
            for line in iwdl_brw.invoice_id.invoice_line:
                if line.concept_id.id == concept_id:
                    base += f_xc(line.price_subtotal)

            rate_tuple = self._get_rate(cr,
                                        uid,
                                        concept_id,
                                        residence,
                                        nature,
                                        base=0.0,
                                        inv_brw=iwdl_brw.invoice_id,
                                        context=context)

            if rate_tuple[7]:
                apply_income = True
            else:
                apply_income = (apply_income and
                                base >= rate_tuple[0] * rate_tuple[1] / 100.0)
            sb_concept = apply_income and rate_tuple[3] or 0.0
            if apply_income:
                wh_concept = ((rate_tuple[0] / 100.0) * rate_tuple[2] * base /
                              100.0)
                wh_concept -= sb_concept
        values = {
            'amount': wh_concept,
            'raw_tax_ut': money2ut(cr, uid, wh_concept, ut_date),
            'subtract': sb_concept,
            'base_amount': base * (rate_tuple[0] / 100.0),
            'raw_base_ut': money2ut(cr, uid, base, ut_date),
            'retencion_islr': rate_tuple[2],
            'islr_rates_id': rate_tuple[5],
        }
        iwdl_obj.write(cr, uid, ids[0], values, context=context)
        return True
Пример #9
0
    def _save_file(self, path, b64_file):
        """Save a file encoded in base 64"""
        self._check_filestore(path)
        with open(path, 'w') as ofile:
            ofile.write(base64.b64decode(b64_file))
        return True

    def _set_image(self, cr, uid, id, name, value, arg, context=None):
        image = self.browse(cr, uid, id, context=context)
        full_path = self._image_path(cr, uid, image, context=context)
        if full_path:
            return self._save_file(full_path, value)
        return self.write(cr, uid, id, {'file_db_store' : value}, context=context)

    _columns = {
        'name':fields.char('Image Title', size=100, required=True),
        'extention': fields.char('file extention', size=6),
        'link':fields.boolean('Link?', help="Images can be linked from files on your file system or remote (Preferred)"),
        'file_db_store':fields.binary('Image stored in database'),
        'file':fields.function(_get_image, fnct_inv=_set_image, type="binary", filters='*.png,*.jpg,*.gif'),
        'url':fields.char('File Location', size=250),
        'comments':fields.text('Comments'),
        'product_id':fields.many2one('product.product', 'Product')
        }
    _defaults = {
        'link': lambda *a: False,
        }
    _sql_constraints = [('uniq_name_product_id', 'UNIQUE(product_id, name)',
                         _('A product can have only one image with the same name'))]

Пример #10
0
                _logger.warning('Data not found for items of %s %s', module_rec.name, str(e))
            except Exception, e:
                _logger.warning('Unknown error while fetching data of %s', module_rec.name, exc_info=True)

        for key in res.iterkeys():
            res[key]['models_by_module'] = '<table width="100%"><tr>' \
                + '<th colspan="2" style="text-align: center;">Models</th></tr><tr>' \
                + '<th>Name</th><th>Technical Name</th></tr><tr>' \
                + '</tr><tr>'.join(sorted(res[key]['models_by_module'])) \
                + '</tr></table>'
            res[key]['fields_by_module'] = '<table width="100%"><tr>' \
                + '<th colspan="8" style="text-align: center;">Fields</th></tr><tr>' \
                + '<th>Name</th><th>Technical Name</th>' \
                + '<th>Model</th><th>ModelTechnical Name</th>' \
                + '<th>Type</th><th>Object Relation</th>' \
                + '<th>Required</th><th>Readonly</th></tr><tr>' \
                + '</tr><tr>'.join(sorted(res[key]['fields_by_module'])) \
                + '</tr></table>'
            res[key]['data_by_module'] = '<table width="100%"><tr>' \
                + '<th colspan="4" style="text-align: center;">Data Records</th></tr><tr>' \
                + '<th>XML ID</th><th>Model</th><th>Model Technical Name</th><th>ID</th></tr><tr>' \
                + '</tr><tr>'.join(sorted(res[key]['data_by_module'])) \
                + '</tr></table>'
        return res

    _columns = {
        'models_by_module': fields.function(_get_model_data, string='Models', type='html', multi="metadata"),
        'fields_by_module': fields.function(_get_model_data, string='Fields', type='html', multi="metadata"),
        'data_by_module': fields.function(_get_model_data, string='Data', type='html', multi="metadata"),
    }
Пример #11
0
    Employee
    '''

    _inherit = 'hr.employee'

    def _payslip_count(self, cr, uid, ids, field_name, arg, context=None):
        try:
            res = super(hr_employee, self)._payslip_count(cr, uid, ids, field_name, arg, context)
        except AccessError, e:
            res = {
                employee_id: 0
                for employee_id in ids
            }
        return res
    _columns = {
        'payslip_count': old_fields.function(_payslip_count, type='integer', string='Payslips'),
    }

    def _get_access_to_employee_information(self):
        access_by_group = self.env.ref('access_custom.group_employee_private_information').id in self.env.user.groups_id.ids
        for r in self:
            r.access_to_employee_information = access_by_group or (r.user_id.id == self.env.uid)

    access_to_employee_information = fields.Boolean('Access to employee information', compute=_get_access_to_employee_information, store=False)


class res_partner(models.Model):
    _inherit = 'res.partner'

    @api.multi
    def read(self, fields=None, load='_classic_read'):
Пример #12
0
    def _sale_order_count(self, cr, uid, ids, field_name, arg, context=None):
        res = dict(map(lambda x: (x,0), ids))
        # The current user may not have access rights for sale orders
        try:
            for partner in self.browse(cr, uid, ids, context):
                res[partner.id] = self.get_partner_sales(cr, uid, partner)
                for child in partner.mapped('child_ids'):
                    res[partner.id] += self.get_partner_sales(cr, uid, child)
        except Exception, e:
            pass

        return res

    def _sale_quote_count(self, cr, uid, ids, field_name, arg, context=None):
        res = dict(map(lambda x: (x,0), ids))
        # The current user may not have access rights for sale orders
        try:
            for partner in self.browse(cr, uid, ids, context):
                res[partner.id] = self.get_partner_quotes(cr, uid, partner)
                for child in partner.mapped('child_ids'):
                    res[partner.id] += self.get_partner_quotes(cr, uid, child)
        except Exception, e:
            print e
            pass
        return res

    _columns = {
        'sale_order_count': fields.function(_sale_order_count, string='# of Sales Order', type='integer'),
        'sale_quote_count': fields.function(_sale_quote_count, string='# of Quotes', type='integer'),
    }
Пример #13
0
class IrMail(orm.Model):
    _inherit = "ir.mail_server"

    def _get_smtp_conf(self, cr, uid, ids, name, args, context=None):
        """
        Return configuration
        """
        res = {}
        for mail_server in self.browse(cr, uid, ids, context=context):
            global_section_name = 'outgoing_mail'

            # default vals
            config_vals = {'smtp_port': 587}
            if serv_config.has_section(global_section_name):
                config_vals.update((serv_config.items(global_section_name)))

            custom_section_name = '.'.join(
                (global_section_name, mail_server.name))
            if serv_config.has_section(custom_section_name):
                config_vals.update(serv_config.items(custom_section_name))

            if config_vals.get('smtp_port'):
                config_vals['smtp_port'] = int(config_vals['smtp_port'])

            res[mail_server.id] = config_vals
        return res

    _columns = {
        'smtp_host':
        fields.function(_get_smtp_conf,
                        string='SMTP Server',
                        type="char",
                        multi='outgoing_mail_config',
                        states={'draft': [('readonly', True)]},
                        help="Hostname or IP of SMTP server"),
        'smtp_port':
        fields.function(_get_smtp_conf,
                        string='SMTP Port',
                        type="integer",
                        multi='outgoing_mail_config',
                        states={'draft': [('readonly', True)]},
                        help="SMTP Port. Usually 465 for SSL, "
                        "and 25 or 587 for other cases.",
                        size=5),
        'smtp_user':
        fields.function(_get_smtp_conf,
                        string='Username',
                        type="char",
                        multi='outgoing_mail_config',
                        states={'draft': [('readonly', True)]},
                        help="Optional username for SMTP authentication",
                        size=64),
        'smtp_pass':
        fields.function(_get_smtp_conf,
                        string='Password',
                        type="char",
                        multi='outgoing_mail_config',
                        states={'draft': [('readonly', True)]},
                        help="Optional password for SMTP authentication",
                        size=64),
        'smtp_encryption':
        fields.function(_get_smtp_conf,
                        string='smtp_encryption',
                        type="selection",
                        multi='outgoing_mail_config',
                        selection=[('none', 'None'),
                                   ('starttls', 'TLS (STARTTLS)'),
                                   ('ssl', 'SSL/TLS')],
                        states={'draft': [('readonly', True)]},
                        help="Choose the connection encryption scheme:\n"
                        "- none: SMTP sessions are done in cleartext.\n"
                        "- starttls: TLS encryption is requested at start "
                        "of SMTP session (Recommended)\n"
                        "- ssl: SMTP sessions are encrypted with SSL/TLS "
                        "through a dedicated port (default: 465)")
    }
Пример #14
0
class FetchmailServer(orm.Model):
    """Incoming POP/IMAP mail server account"""
    _inherit = 'fetchmail.server'

    def _get_incom_conf(self, cr, uid, ids, name, args, context=None):
        """
        Return configuration
        """
        res = {}
        for fetchmail in self.browse(cr, uid, ids, context=context):
            global_section_name = 'incoming_mail'

            key_types = {
                'port': int,
                'is_ssl': lambda a: bool(int(a)),
                'attach': lambda a: bool(int(a)),
                'original': lambda a: bool(int(a)),
            }

            # default vals
            config_vals = {
                'port': 993,
                'is_ssl': 0,
                'attach': 0,
                'original': 0,
            }
            if serv_config.has_section(global_section_name):
                config_vals.update(serv_config.items(global_section_name))

            custom_section_name = '.'.join(
                (global_section_name, fetchmail.name))
            if serv_config.has_section(custom_section_name):
                config_vals.update(serv_config.items(custom_section_name))

            for key, to_type in key_types.iteritems():
                if config_vals.get(key):
                    config_vals[key] = to_type(config_vals[key])
            res[fetchmail.id] = config_vals
        return res

    def _type_search(self, cr, uid, obj, name, args, context=None):
        result_ids = []
        # read all incoming servers values
        all_ids = self.search(cr, uid, [], context=context)
        results = self.read(cr, uid, all_ids, ['id', 'type'], context=context)
        args = args[:]
        i = 0
        while i < len(args):
            operator = args[i][1]
            if operator == '=':
                for res in results:
                    if (res['type'] == args[i][2]
                            and res['id'] not in result_ids):
                        result_ids.append(res['id'])
            elif operator == 'in':
                for search_vals in args[i][2]:
                    for res in results:
                        if (res['type'] == search_vals
                                and res['id'] not in result_ids):
                            result_ids.append(res['id'])
            else:
                continue
            i += 1
        return [('id', 'in', result_ids)]

    _columns = {
        'server':
        fields.function(_get_incom_conf,
                        string='Server',
                        type="char",
                        multi='income_mail_config',
                        states={'draft': [('readonly', True)]},
                        help="Hostname or IP of the mail server"),
        'port':
        fields.function(_get_incom_conf,
                        string='Port',
                        type="integer",
                        states={'draft': [('readonly', True)]},
                        multi='income_mail_config'),
        'type':
        fields.function(_get_incom_conf,
                        string='Type',
                        type="selection",
                        selection=[
                            ('pop', 'POP Server'),
                            ('imap', 'IMAP Server'),
                            ('local', 'Local Server'),
                        ],
                        multi='income_mail_config',
                        fnct_search=_type_search,
                        states={'draft': [('readonly', True)]},
                        help="pop, imap, local"),
        'is_ssl':
        fields.function(_get_incom_conf,
                        string='Is SSL',
                        type="boolean",
                        multi='income_mail_config',
                        states={'draft': [('readonly', True)]},
                        help='Connections are encrypted with SSL/TLS through'
                        ' a dedicated port (default: IMAPS=993, POP3S=995)'),
        'attach':
        fields.function(
            _get_incom_conf,
            string='Keep Attachments',
            type="boolean",
            multi='income_mail_config',
            states={'draft': [('readonly', True)]},
            help="Whether attachments should be downloaded. "
            "If not enabled, incoming emails will be stripped of any "
            "attachments before being processed"),
        'original':
        fields.function(
            _get_incom_conf,
            string='Keep Original',
            type="boolean",
            multi='income_mail_config',
            states={'draft': [('readonly', True)]},
            help="Whether a full original copy of each email should be kept "
            "for reference and attached to each processed message. This "
            "will usually double the size of your message database."),
        'user':
        fields.function(_get_incom_conf,
                        string='Username',
                        type="char",
                        states={'draft': [('readonly', True)]},
                        multi='income_mail_config'),
        'password':
        fields.function(_get_incom_conf,
                        string='password',
                        type="char",
                        states={'draft': [('readonly', True)]},
                        multi='income_mail_config')
    }
Пример #15
0
class res_partner_category(osv.osv):
    def name_get(self, cr, uid, ids, context=None):
        """Return the categories' display name, including their direct
           parent by default.

        :param dict context: the ``partner_category_display`` key can be
                             used to select the short version of the
                             category name (without the direct parent),
                             when set to ``'short'``. The default is
                             the long version."""
        if context is None:
            context = {}
        if context.get('partner_category_display') == 'short':
            return super(res_partner_category, self).name_get(cr,
                                                              uid,
                                                              ids,
                                                              context=context)
        if isinstance(ids, (int, long)):
            ids = [ids]
        reads = self.read(cr, uid, ids, ['name', 'parent_id'], context=context)
        res = []
        for record in reads:
            name = record['name']
            if record['parent_id']:
                name = record['parent_id'][1] + ' / ' + name
            res.append((record['id'], name))
        return res

    def name_search(self,
                    cr,
                    uid,
                    name,
                    args=None,
                    operator='ilike',
                    context=None,
                    limit=100):
        if not args:
            args = []
        if not context:
            context = {}
        if name:
            # Be sure name_search is symetric to name_get
            name = name.split(' / ')[-1]
            ids = self.search(cr,
                              uid, [('name', operator, name)] + args,
                              limit=limit,
                              context=context)
        else:
            ids = self.search(cr, uid, args, limit=limit, context=context)
        return self.name_get(cr, uid, ids, context)

    def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
        res = self.name_get(cr, uid, ids, context=context)
        return dict(res)

    _description = 'Partner Categories'
    _name = 'res.partner.category'
    _columns = {
        'name':
        fields.char('Category Name', required=True, size=64, translate=True),
        'parent_id':
        fields.many2one('res.partner.category',
                        'Parent Category',
                        select=True,
                        ondelete='cascade'),
        'complete_name':
        fields.function(_name_get_fnc, type="char", string='Full Name'),
        'child_ids':
        fields.one2many('res.partner.category', 'parent_id',
                        'Child Categories'),
        'active':
        fields.boolean(
            'Active',
            help=
            "The active field allows you to hide the category without removing it."
        ),
        'parent_left':
        fields.integer('Left parent', select=True),
        'parent_right':
        fields.integer('Right parent', select=True),
        'partner_ids':
        fields.many2many('res.partner',
                         id1='category_id',
                         id2='partner_id',
                         string='Partners'),
    }
    _constraints = [
        (osv.osv._check_recursion,
         'Error ! You can not create recursive categories.', ['parent_id'])
    ]
    _defaults = {
        'active': 1,
    }
    _parent_store = True
    _parent_order = 'name'
    _order = 'parent_left'
Пример #16
0
class res_partner(osv.osv, format_address):
    _description = 'Partner'
    _name = "res.partner"

    def _address_display(self, cr, uid, ids, name, args, context=None):
        res = {}
        for partner in self.browse(cr, uid, ids, context=context):
            res[partner.id] = self._display_address(cr,
                                                    uid,
                                                    partner,
                                                    context=context)
        return res

    def _get_image(self, cr, uid, ids, name, args, context=None):
        result = dict.fromkeys(ids, False)
        for obj in self.browse(cr, uid, ids, context=context):
            result[obj.id] = tools.image_get_resized_images(obj.image)
        return result

    def _get_tz_offset(self, cr, uid, ids, name, args, context=None):
        result = dict.fromkeys(ids, False)
        for obj in self.browse(cr, uid, ids, context=context):
            result[obj.id] = datetime.datetime.now(
                pytz.timezone(obj.tz or 'GMT')).strftime('%z')
        return result

    def _set_image(self, cr, uid, id, name, value, args, context=None):
        return self.write(cr,
                          uid, [id],
                          {'image': tools.image_resize_image_big(value)},
                          context=context)

    def _has_image(self, cr, uid, ids, name, args, context=None):
        result = {}
        for obj in self.browse(cr, uid, ids, context=context):
            result[obj.id] = obj.image != False
        return result

    _order = "name"
    _columns = {
        'name': fields.char('Name', size=128, required=True, select=True),
        'date': fields.date('Date', select=1),
        'title': fields.many2one('res.partner.title', 'Title'),
        'parent_id': fields.many2one('res.partner', 'Related Company'),
        'child_ids': fields.one2many('res.partner', 'parent_id', 'Contacts'),
        'ref': fields.char('Reference', size=64, select=1),
        'lang': fields.selection(_lang_get, 'Language',
            help="If the selected language is loaded in the system, all documents related to this contact will be printed in this language. If not, it will be English."),
        'tz': fields.selection(_tz_get,  'Timezone', size=64,
            help="The partner's timezone, used to output proper date and time values inside printed reports. "
                 "It is important to set a value for this field. You should use the same timezone "
                 "that is otherwise used to pick and render date and time values: your computer's timezone."),
        'tz_offset': fields.function(_get_tz_offset, type='char', size=5, string='Timezone offset', invisible=True),
        'user_id': fields.many2one('res.users', 'Salesperson', help='The internal user that is in charge of communicating with this contact if any.'),
        'vat': fields.char('TIN', size=32, help="Tax Identification Number. Check the box if this contact is subjected to taxes. Used by the some of the legal statements."),
        'bank_ids': fields.one2many('res.partner.bank', 'partner_id', 'Banks'),
        'website': fields.char('Website', size=64, help="Website of Partner or Company"),
        'comment': fields.text('Notes'),
        'category_id': fields.many2many('res.partner.category', id1='partner_id', id2='category_id', string='Tags'),
        'credit_limit': fields.float(string='Credit Limit'),
        'ean13': fields.char('EAN13', size=13),
        'active': fields.boolean('Active'),
        'customer': fields.boolean('Customer', help="Check this box if this contact is a customer."),
        'supplier': fields.boolean('Supplier', help="Check this box if this contact is a supplier. If it's not checked, purchase people will not see it when encoding a purchase order."),
        'employee': fields.boolean('Employee', help="Check this box if this contact is an Employee."),
        'function': fields.char('Job Position', size=128),
        'type': fields.selection([('default', 'Default'), ('invoice', 'Invoice'),
                                   ('delivery', 'Shipping'), ('contact', 'Contact'),
                                   ('other', 'Other')], 'Address Type',
            help="Used to select automatically the right address according to the context in sales and purchases documents."),
        'street': fields.char('Street', size=128),
        'street2': fields.char('Street2', size=128),
        'zip': fields.char('Zip', change_default=True, size=24),
        'city': fields.char('City', size=128),
        'state_id': fields.many2one("res.country.state", 'State'),
        'country_id': fields.many2one('res.country', 'Country'),
        'country': fields.related('country_id', type='many2one', relation='res.country', string='Country',
                                  deprecated="This field will be removed as of OpenERP 7.1, use country_id instead"),
        'email': fields.char('Email', size=240),
        'phone': fields.char('Phone', size=64),
        'fax': fields.char('Fax', size=64),
        'mobile': fields.char('Mobile', size=64),
        'birthdate': fields.char('Birthdate', size=64),
        'is_company': fields.boolean('Is a Company', help="Check if the contact is a company, otherwise it is a person"),
        'use_parent_address': fields.boolean('Use Company Address', help="Select this if you want to set company's address information  for this contact"),
        # image: all image fields are base64 encoded and PIL-supported
        'image': fields.binary("Image",
            help="This field holds the image used as avatar for this contact, limited to 1024x1024px"),
        'image_medium': fields.function(_get_image, fnct_inv=_set_image,
            string="Medium-sized image", type="binary", multi="_get_image",
            store={
                'res.partner': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
            },
            help="Medium-sized image of this contact. It is automatically "\
                 "resized as a 128x128px image, with aspect ratio preserved. "\
                 "Use this field in form views or some kanban views."),
        'image_small': fields.function(_get_image, fnct_inv=_set_image,
            string="Small-sized image", type="binary", multi="_get_image",
            store={
                'res.partner': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
            },
            help="Small-sized image of this contact. It is automatically "\
                 "resized as a 64x64px image, with aspect ratio preserved. "\
                 "Use this field anywhere a small image is required."),
        'has_image': fields.function(_has_image, type="boolean"),
        'company_id': fields.many2one('res.company', 'Company', select=1),
        'color': fields.integer('Color Index'),
        'user_ids': fields.one2many('res.users', 'partner_id', 'Users'),
        'contact_address': fields.function(_address_display,  type='char', string='Complete Address'),
    }

    def _default_category(self, cr, uid, context=None):
        if context is None:
            context = {}
        if context.get('category_id'):
            return [context['category_id']]
        return False

    def _get_default_image(self,
                           cr,
                           uid,
                           is_company,
                           context=None,
                           colorize=False):
        img_path = openerp.modules.get_module_resource(
            'base', 'static/src/img',
            ('company_image.png' if is_company else 'avatar.png'))
        with open(img_path, 'rb') as f:
            image = f.read()

        # colorize user avatars
        if not is_company:
            image = tools.image_colorize(image)

        return tools.image_resize_image_big(image.encode('base64'))

    def fields_view_get(self,
                        cr,
                        user,
                        view_id=None,
                        view_type='form',
                        context=None,
                        toolbar=False,
                        submenu=False):
        if (not view_id) and (view_type == 'form') and context and context.get(
                'force_email', False):
            view_id = self.pool.get('ir.model.data').get_object_reference(
                cr, user, 'base', 'view_partner_simple_form')[1]
        res = super(res_partner, self).fields_view_get(cr,
                                                       user,
                                                       view_id,
                                                       view_type,
                                                       context,
                                                       toolbar=toolbar,
                                                       submenu=submenu)
        if view_type == 'form':
            res['arch'] = self.fields_view_get_address(cr,
                                                       user,
                                                       res['arch'],
                                                       context=context)
        return res

    _defaults = {
        'active':
        True,
        'lang':
        lambda self, cr, uid, ctx: ctx.get('lang', 'en_US'),
        'tz':
        lambda self, cr, uid, ctx: ctx.get('tz', False),
        'customer':
        True,
        'category_id':
        _default_category,
        'company_id':
        lambda self, cr, uid, ctx: self.pool.get('res.company').
        _company_default_get(cr, uid, 'res.partner', context=ctx),
        'color':
        0,
        'is_company':
        False,
        'type':
        'default',
        'use_parent_address':
        True,
        'image':
        False,
    }

    def copy(self, cr, uid, id, default=None, context=None):
        if default is None:
            default = {}
        name = self.read(cr, uid, [id], ['name'], context)[0]['name']
        default.update({'name': _('%s (copy)') % name})
        return super(res_partner, self).copy(cr, uid, id, default, context)

    def onchange_type(self, cr, uid, ids, is_company, context=None):
        value = {}
        value['title'] = False
        if is_company:
            value['parent_id'] = False
            domain = {'title': [('domain', '=', 'partner')]}
        else:
            domain = {'title': [('domain', '=', 'contact')]}
        return {'value': value, 'domain': domain}

    def onchange_address(self,
                         cr,
                         uid,
                         ids,
                         use_parent_address,
                         parent_id,
                         context=None):
        def value_or_id(val):
            """ return val or val.id if val is a browse record """
            return val if isinstance(val, (bool, int, long, float,
                                           basestring)) else val.id

        if use_parent_address and parent_id:
            parent = self.browse(cr, uid, parent_id, context=context)
            return {
                'value':
                dict((key, value_or_id(parent[key])) for key in ADDRESS_FIELDS)
            }
        return {}

    def onchange_state(self, cr, uid, ids, state_id, context=None):
        if state_id:
            country_id = self.pool.get('res.country.state').browse(
                cr, uid, state_id, context).country_id.id
            return {'value': {'country_id': country_id}}
        return {}

    def _check_ean_key(self, cr, uid, ids, context=None):
        for partner_o in pooler.get_pool(cr.dbname).get('res.partner').read(
                cr, uid, ids, [
                    'ean13',
                ]):
            thisean = partner_o['ean13']
            if thisean and thisean != '':
                if len(thisean) != 13:
                    return False
                sum = 0
                for i in range(12):
                    if not (i % 2):
                        sum += int(thisean[i])
                    else:
                        sum += 3 * int(thisean[i])
                if math.ceil(sum / 10.0) * 10 - sum != int(thisean[12]):
                    return False
        return True

#   _constraints = [(_check_ean_key, 'Error: Invalid ean code', ['ean13'])]

    def write(self, cr, uid, ids, vals, context=None):
        # Update parent and siblings or children records
        if isinstance(ids, (int, long)):
            ids = [ids]
        if vals.get('is_company') == False:
            vals.update({'child_ids': [(5, )]})
        for partner in self.browse(cr, uid, ids, context=context):
            update_ids = []
            if partner.is_company:
                domain_children = [('parent_id', '=', partner.id),
                                   ('use_parent_address', '=', True)]
                update_ids = self.search(cr,
                                         uid,
                                         domain_children,
                                         context=context)
            elif partner.parent_id:
                if vals.get('use_parent_address') == True:
                    domain_siblings = [('parent_id', '=',
                                        partner.parent_id.id),
                                       ('use_parent_address', '=', True)]
                    update_ids = [partner.parent_id.id] + self.search(
                        cr, uid, domain_siblings, context=context)
                if 'use_parent_address' not in vals and partner.use_parent_address:
                    domain_siblings = [('parent_id', '=',
                                        partner.parent_id.id),
                                       ('use_parent_address', '=', True)]
                    update_ids = [partner.parent_id.id] + self.search(
                        cr, uid, domain_siblings, context=context)
            self.update_address(cr, uid, update_ids, vals, context)
        return super(res_partner, self).write(cr,
                                              uid,
                                              ids,
                                              vals,
                                              context=context)

    def create(self, cr, uid, vals, context=None):
        if context is None:
            context = {}
        # Update parent and siblings records
        if vals.get('parent_id') and vals.get('use_parent_address'):
            domain_siblings = [('parent_id', '=', vals['parent_id']),
                               ('use_parent_address', '=', True)]
            update_ids = [vals['parent_id']] + self.search(
                cr, uid, domain_siblings, context=context)
            self.update_address(cr, uid, update_ids, vals, context)
        return super(res_partner, self).create(cr, uid, vals, context=context)

    def update_address(self, cr, uid, ids, vals, context=None):
        addr_vals = dict(
            (key, vals[key]) for key in POSTAL_ADDRESS_FIELDS if vals.get(key))
        if addr_vals:
            return super(res_partner, self).write(cr, uid, ids, addr_vals,
                                                  context)

    def name_get(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        if isinstance(ids, (int, long)):
            ids = [ids]
        res = []
        for record in self.browse(cr, uid, ids, context=context):
            name = record.name
            if record.parent_id:
                name = "%s (%s)" % (name, record.parent_id.name)
            if context.get('show_address'):
                name = name + "\n" + self._display_address(
                    cr, uid, record, without_company=True, context=context)
                name = name.replace('\n\n', '\n')
                name = name.replace('\n\n', '\n')
            if context.get('show_email') and record.email:
                name = "%s <%s>" % (name, record.email)
            res.append((record.id, name))
        return res

    def _parse_partner_name(self, text, context=None):
        """ Supported syntax:
            - 'Raoul <*****@*****.**>': will find name and email address
            - otherwise: default, everything is set as the name """
        match = re.search(r'([^\s,<@]+@[^>\s,]+)', text)
        if match:
            email = match.group(1)
            name = text[:text.index(email)].replace('"',
                                                    '').replace('<',
                                                                '').strip()
        else:
            name, email = text, ''
        return name, email

    def name_create(self, cr, uid, name, context=None):
        """ Override of orm's name_create method for partners. The purpose is
            to handle some basic formats to create partners using the
            name_create.
            If only an email address is received and that the regex cannot find
            a name, the name will have the email value.
            If 'force_email' key in context: must find the email address. """
        if context is None:
            context = {}
        name, email = self._parse_partner_name(name, context=context)
        if context.get('force_email') and not email:
            raise osv.except_osv(
                _('Warning'),
                _("Couldn't create contact without email address !"))
        if not name and email:
            name = email
        rec_id = self.create(cr,
                             uid, {
                                 self._rec_name: name or email,
                                 'email': email or False
                             },
                             context=context)
        return self.name_get(cr, uid, [rec_id], context)[0]

    def name_search(self,
                    cr,
                    uid,
                    name,
                    args=None,
                    operator='ilike',
                    context=None,
                    limit=100):
        if not args:
            args = []
        if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):
            # search on the name of the contacts and of its company
            search_name = name
            if operator in ('ilike', 'like'):
                search_name = '%%%s%%' % name
            if operator in ('=ilike', '=like'):
                operator = operator[1:]
            query_args = {'name': search_name}
            limit_str = ''
            if limit:
                limit_str = ' limit %(limit)s'
                query_args['limit'] = limit
            cr.execute(
                '''SELECT partner.id FROM res_partner partner
                          LEFT JOIN res_partner company ON partner.parent_id = company.id
                          WHERE partner.email ''' + operator + ''' %(name)s
                             OR partner.name || ' (' || COALESCE(company.name,'') || ')'
                          ''' + operator + ' %(name)s ' + limit_str,
                query_args)
            ids = map(lambda x: x[0], cr.fetchall())
            ids = self.search(cr,
                              uid, [('id', 'in', ids)] + args,
                              limit=limit,
                              context=context)
            if ids:
                return self.name_get(cr, uid, ids, context)
        return super(res_partner, self).name_search(cr,
                                                    uid,
                                                    name,
                                                    args,
                                                    operator=operator,
                                                    context=context,
                                                    limit=limit)

    def find_or_create(self, cr, uid, email, context=None):
        """ Find a partner with the given ``email`` or use :py:method:`~.name_create`
            to create one

            :param str email: email-like string, which should contain at least one email,
                e.g. ``"Raoul Grosbedon <*****@*****.**>"``"""
        assert email, 'an email is required for find_or_create to work'
        emails = tools.email_split(email)
        if emails:
            email = emails[0]
        ids = self.search(cr,
                          uid, [('email', 'ilike', email)],
                          context=context)
        if not ids:
            return self.name_create(cr, uid, email, context=context)[0]
        return ids[0]

    def _email_send(self,
                    cr,
                    uid,
                    ids,
                    email_from,
                    subject,
                    body,
                    on_error=None):
        partners = self.browse(cr, uid, ids)
        for partner in partners:
            if partner.email:
                tools.email_send(email_from, [partner.email], subject, body,
                                 on_error)
        return True

    def email_send(self, cr, uid, ids, email_from, subject, body, on_error=''):
        while len(ids):
            self.pool.get('ir.cron').create(
                cr, uid, {
                    'name': 'Send Partner Emails',
                    'user_id': uid,
                    'model': 'res.partner',
                    'function': '_email_send',
                    'args': repr(
                        [ids[:16], email_from, subject, body, on_error])
                })
            ids = ids[16:]
        return True

    def address_get(self, cr, uid, ids, adr_pref=None):
        if adr_pref is None:
            adr_pref = ['default']
        result = {}
        # retrieve addresses from the partner itself and its children
        res = []
        # need to fix the ids ,It get False value in list like ids[False]
        if ids and ids[0] != False:
            for p in self.browse(cr, uid, ids):
                res.append((p.type, p.id))
                res.extend((c.type, c.id) for c in p.child_ids)
        address_dict = dict(reversed(res))
        # get the id of the (first) default address if there is one,
        # otherwise get the id of the first address in the list
        default_address = False
        if res:
            default_address = address_dict.get('default', res[0][1])
        for adr in adr_pref:
            result[adr] = address_dict.get(adr, default_address)
        return result

    def view_header_get(self, cr, uid, view_id, view_type, context):
        res = super(res_partner, self).view_header_get(cr, uid, view_id,
                                                       view_type, context)
        if res: return res
        if not context.get('category_id', False):
            return False
        return _('Partners: ') + self.pool.get('res.partner.category').browse(
            cr, uid, context['category_id'], context).name

    def main_partner(self, cr, uid):
        ''' Return the id of the main partner
        '''
        model_data = self.pool.get('ir.model.data')
        return model_data.browse(
            cr,
            uid,
            model_data.search(cr, uid, [('module', '=', 'base'),
                                        ('name', '=', 'main_partner')])[0],
        ).res_id

    def _display_address(self,
                         cr,
                         uid,
                         address,
                         without_company=False,
                         context=None):
        '''
        The purpose of this function is to build and return an address formatted accordingly to the
        standards of the country where it belongs.

        :param address: browse record of the res.partner to format
        :returns: the address formatted in a display that fit its country habits (or the default ones
            if not country is specified)
        :rtype: string
        '''

        # get the information that will be injected into the display format
        # get the address format
        address_format = address.country_id and address.country_id.address_format or \
              "%(street)s\n%(street2)s\n%(city)s %(state_code)s %(zip)s\n%(country_name)s"
        args = {
            'state_code': address.state_id and address.state_id.code or '',
            'state_name': address.state_id and address.state_id.name or '',
            'country_code': address.country_id and address.country_id.code
            or '',
            'country_name': address.country_id and address.country_id.name
            or '',
            'company_name': address.parent_id and address.parent_id.name or '',
        }
        address_field = ['title', 'street', 'street2', 'zip', 'city']
        for field in address_field:
            args[field] = getattr(address, field) or ''
        if without_company:
            args['company_name'] = ''
        elif address.parent_id:
            address_format = '%(company_name)s\n' + address_format
        return address_format % args
class booking_chart(osv.osv):

    _name = "booking.chart"
    _description = "Booking Chart"

    def extra_fields(self, cr, uid, ids, field_names, arg, context=None):
        result = {}
        supported_models = []
        for chart in self.browse(cr, uid, ids, context=context):

            for supported_model in chart.supported_model_ids:
                supported_models.append(
                    (supported_model.model, supported_model.name))

            result[chart.id] = {
                'resource_model_name': chart.resource_model.model,
                'supported_models': supported_models
            }

        return result

    _columns = {
        'name':
        fields.char('Chart Name'),
        'resource_model':
        fields.many2one(
            'ir.model',
            'Model of the Resource',
            required=True,
            help='OpenERP model that represents the booked resource.'),
        'resource_domain':
        fields.char('Domain to filter the resources',
                    help='''This Domain has the format of an domain expression
            (see: https://doc.openerp.com/trunk/web/rpc/ ). It is used if we want to display only some resources
            filtered based on that domain. Example: [["is_company","=",false]]'''
                    ),
        'resource_name':
        fields.char('Resource Name'),
        'supported_model_ids':
        fields.many2many(
            'ir.model',
            'booking_chart_to_model_rel',
            id1='chart_id',
            id2='model_id',
            required=True,
            string='Target/Orgin Resource Models',
            help='Models used for Resource Booking Target and Origin.'),
        'resource_model_name':
        fields.function(extra_fields,
                        method=True,
                        type='serialized',
                        string='Resource Model Name',
                        multi=True,
                        readonly=True),
        'supported_models':
        fields.function(extra_fields,
                        method=True,
                        type='serialized',
                        string='Supported Model Array',
                        multi=True,
                        readonly=True)
    }
Пример #18
0
class im_livechat_channel(osv.osv):
    _name = 'im_livechat.channel'

    def _get_default_image(self, cr, uid, context=None):
        image_path = openerp.modules.get_module_resource(
            'im_livechat', 'static/src/img', 'default.png')
        return tools.image_resize_image_big(
            open(image_path, 'rb').read().encode('base64'))

    def _get_image(self, cr, uid, ids, name, args, context=None):
        result = dict.fromkeys(ids, False)
        for obj in self.browse(cr, uid, ids, context=context):
            result[obj.id] = tools.image_get_resized_images(obj.image)
        return result

    def _set_image(self, cr, uid, id, name, value, args, context=None):
        return self.write(cr,
                          uid, [id],
                          {'image': tools.image_resize_image_big(value)},
                          context=context)

    def _are_you_inside(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for record in self.browse(cr, uid, ids, context=context):
            res[record.id] = False
            for user in record.user_ids:
                if user.id == uid:
                    res[record.id] = True
                    break
        return res

    def _script(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for record in self.browse(cr, uid, ids, context=context):
            res[record.id] = env.get_template("include.html").render({
                "url":
                self.pool.get('ir.config_parameter').get_param(
                    cr, uid, 'web.base.url'),
                "parameters": {
                    "db": cr.dbname,
                    "channel": record.id
                },
            })
        return res

    def _web_page(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for record in self.browse(cr, uid, ids, context=context):
            res[record.id] = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + \
                "/im_livechat/web_page?p=" + json.dumps({"db":cr.dbname, "channel":record.id})
        return res

    _columns = {
        'name': fields.char(string="Channel Name", size=200, required=True),
        'user_ids': fields.many2many('res.users', 'im_livechat_channel_im_user', 'channel_id', 'user_id', string="Users"),
        'are_you_inside': fields.function(_are_you_inside, type='boolean', string='Are you inside the matrix?', store=False),
        'script': fields.function(_script, type='text', string='Script', store=False),
        'web_page': fields.function(_web_page, type='url', string='Web Page', store=False, size="200"),
        'button_text': fields.char(string="Text of the Button", size=200),
        'input_placeholder': fields.char(string="Chat Input Placeholder", size=200),
        'default_message': fields.char(string="Welcome Message", size=200, help="This is an automated 'welcome' message that your visitor will see when they initiate a new chat session."),
        # image: all image fields are base64 encoded and PIL-supported
        'image': fields.binary("Photo",
            help="This field holds the image used as photo for the group, limited to 1024x1024px."),
        'image_medium': fields.function(_get_image, fnct_inv=_set_image,
            string="Medium-sized photo", type="binary", multi="_get_image",
            store={
                'im_livechat.channel': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
            },
            help="Medium-sized photo of the group. It is automatically "\
                 "resized as a 128x128px image, with aspect ratio preserved. "\
                 "Use this field in form views or some kanban views."),
        'image_small': fields.function(_get_image, fnct_inv=_set_image,
            string="Small-sized photo", type="binary", multi="_get_image",
            store={
                'im_livechat.channel': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
            },
            help="Small-sized photo of the group. It is automatically "\
                 "resized as a 64x64px image, with aspect ratio preserved. "\
                 "Use this field anywhere a small image is required."),
    }

    def _default_user_ids(self, cr, uid, context=None):
        return [(6, 0, [uid])]

    _defaults = {
        'button_text': "Have a Question? Chat with us.",
        'input_placeholder': "How may I help you?",
        'default_message': '',
        'user_ids': _default_user_ids,
        'image': _get_default_image,
    }

    def get_available_users(self, cr, uid, channel_id, context=None):
        channel = self.browse(cr,
                              openerp.SUPERUSER_ID,
                              channel_id,
                              context=context)
        im_user_ids = self.pool.get("im.user").search(
            cr,
            uid, [["user_id", "in", [user.id for user in channel.user_ids]]],
            context=context)
        users = []
        for iuid in im_user_ids:
            imuser = self.pool.get("im.user").browse(cr,
                                                     uid,
                                                     iuid,
                                                     context=context)
            if imuser.im_status:
                users.append(imuser)
        return users

    def get_session(self, cr, uid, channel_id, uuid, context=None):
        self.pool.get("im.user").get_my_id(cr, uid, uuid, context=context)
        users = self.get_available_users(cr,
                                         openerp.SUPERUSER_ID,
                                         channel_id,
                                         context=context)
        if len(users) == 0:
            return False
        user_id = random.choice(users).id
        session = self.pool.get("im.session").session_get(cr,
                                                          uid, [user_id],
                                                          uuid,
                                                          context=context)
        self.pool.get("im.session").write(cr,
                                          openerp.SUPERUSER_ID,
                                          session.get("id"),
                                          {'channel_id': channel_id},
                                          context=context)
        return session.get("id")

    def test_channel(self, cr, uid, channel, context=None):
        if not channel:
            return {}
        return {
            'url': self.browse(cr, uid, channel[0], context=context
                               or {}).web_page,
            'type': 'ir.actions.act_url'
        }

    def get_info_for_chat_src(self, cr, uid, channel, context=None):
        url = self.pool.get('ir.config_parameter').get_param(
            cr, openerp.SUPERUSER_ID, 'web.base.url')
        chan = self.browse(cr, uid, channel, context=context)
        return {
            "url": url,
            'buttonText': chan.button_text,
            'inputPlaceholder': chan.input_placeholder,
            'defaultMessage': chan.default_message,
            "channelName": chan.name,
        }

    def join(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'user_ids': [(4, uid)]})
        return True

    def quit(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'user_ids': [(3, uid)]})
        return True
Пример #19
0
class sale_order_line(orm.Model):
    _inherit = 'sale.order.line'

    def _is_stock_reservable(self, cr, uid, ids, fields, args, context=None):
        result = {}.fromkeys(ids, False)
        for line in self.browse(cr, uid, ids, context=context):
            if line.state != 'draft':
                continue
            if line.type == 'make_to_order':
                continue
            if (not line.product_id or line.product_id.type == 'service'):
                continue
            if not line.reservation_ids:
                result[line.id] = True
        return result

    _columns = {
        'reservation_ids':
        fields.one2many('stock.reservation',
                        'sale_line_id',
                        string='Stock Reservation'),
        'is_stock_reservable':
        fields.function(_is_stock_reservable,
                        type='boolean',
                        readonly=True,
                        string='Can be reserved'),
    }

    def copy_data(self, cr, uid, id, default=None, context=None):
        if default is None:
            default = {}
        default['reservation_ids'] = False
        return super(sale_order_line, self).copy_data(cr,
                                                      uid,
                                                      id,
                                                      default=default,
                                                      context=context)

    def release_stock_reservation(self, cr, uid, ids, context=None):
        lines = self.browse(cr, uid, ids, context=context)
        reserv_ids = [
            reserv.id for line in lines for reserv in line.reservation_ids
        ]
        reserv_obj = self.pool.get('stock.reservation')
        reserv_obj.release(cr, uid, reserv_ids, context=context)
        return True

    def product_id_change(self,
                          cr,
                          uid,
                          ids,
                          pricelist,
                          product,
                          qty=0,
                          uom=False,
                          qty_uos=0,
                          uos=False,
                          name='',
                          partner_id=False,
                          lang=False,
                          update_tax=True,
                          date_order=False,
                          packaging=False,
                          fiscal_position=False,
                          flag=False,
                          context=None):
        result = super(sale_order_line,
                       self).product_id_change(cr,
                                               uid,
                                               ids,
                                               pricelist,
                                               product,
                                               qty=qty,
                                               uom=uom,
                                               qty_uos=qty_uos,
                                               uos=uos,
                                               name=name,
                                               partner_id=partner_id,
                                               lang=lang,
                                               update_tax=update_tax,
                                               date_order=date_order,
                                               packaging=packaging,
                                               fiscal_position=fiscal_position,
                                               flag=flag,
                                               context=context)
        if not ids:  # warn only if we change an existing line
            return result
        assert len(ids) == 1, "Expected 1 ID, got %r" % ids
        line = self.browse(cr, uid, ids[0], context=context)
        if qty != line.product_uom_qty and line.reservation_ids:
            msg = _("As you changed the quantity of the line, "
                    "the quantity of the stock reservation will "
                    "be automatically adjusted to %.2f.") % qty
            msg += "\n\n"
            result.setdefault('warning', {})
            if result['warning'].get('message'):
                result['warning']['message'] += msg
            else:
                result['warning'] = {
                    'title': _('Configuration Error!'),
                    'message': msg,
                }
        return result

    def write(self, cr, uid, ids, vals, context=None):
        block_on_reserve = ('product_id', 'product_uom', 'product_uos', 'type')
        update_on_reserve = ('price_unit', 'product_uom_qty',
                             'product_uos_qty')
        keys = set(vals.keys())
        test_block = keys.intersection(block_on_reserve)
        test_update = keys.intersection(update_on_reserve)
        if test_block:
            for line in self.browse(cr, uid, ids, context=context):
                if not line.reservation_ids:
                    continue
                raise orm.except_orm(
                    _('Error'),
                    _('You cannot change the product or unit of measure '
                      'of lines with a stock reservation. '
                      'Release the reservation '
                      'before changing the product.'))
        res = super(sale_order_line, self).write(cr,
                                                 uid,
                                                 ids,
                                                 vals,
                                                 context=context)
        if test_update:
            for line in self.browse(cr, uid, ids, context=context):
                if not line.reservation_ids:
                    continue
                if len(line.reservation_ids) > 1:
                    raise orm.except_orm(
                        _('Error'),
                        _('Several stock reservations are linked with the '
                          'line. Impossible to adjust their quantity. '
                          'Please release the reservation '
                          'before changing the quantity.'))

                line.reservation_ids[0].write({
                    'price_unit':
                    line.price_unit,
                    'product_qty':
                    line.product_uom_qty,
                    'product_uos_qty':
                    line.product_uos_qty,
                })
        return res
Пример #20
0
    def _setup_analytic_fields(cls, analytic, para, columns, defaults, orm_name, name, bases, nmspc):
        """Generate analytic and para-analytic fields on the model."""

        # If _analytic uses a shortcut, convert it into a prefix-model mapping.
        if analytic is True:
            analytic = {"a": orm_name.replace(".", "_")}
        elif isinstance(analytic, basestring):
            analytic = {"a": analytic}

        # Create a field that will be used for replacement in the view
        if analytic:
            columns["analytic_dimensions"] = fields.function(
                lambda self, cr, uid, ids, *a: {i: "" for i in ids},
                string=u"Analytic Dimensions",
                readonly=True,
                store=False,
            )

        col_pattern = "{pre}{n}_{suf}"
        size = int(config.get_misc("analytic", "analytic_size", 5))

        # Generate the fields directly into the _columns attribute.
        all_analytic = []

        for prefix, model_name in analytic.iteritems():
            # Analytic fields
            all_analytic.append((model_name, prefix, "id"))

            for n in xrange(1, size + 1):
                col_name = col_pattern.format(pre=prefix, n=n, suf="id")
                domain_field = "nd_id.ns{n}_id.model_name".format(n=n)
                columns[col_name] = fields.many2one(
                    "analytic.code",
                    "Generated Analytic Field",
                    domain=[
                        (domain_field, "=", model_name),
                        ("view_type", "=", False),
                        ("disabled_per_company", "=", False),
                    ],
                    track_visibility="onchange",
                )

        for key, value in para.iteritems():
            # Para-analytic fields
            prefix, suffix = key
            model_name = value["model"]
            all_analytic.append((model_name, prefix, suffix))
            if suffix == "id":
                raise ValueError("Para-analytic suffix cannot be 'id'")

            field_type = value["type"]
            args = value["args"]
            kwargs = value["kwargs"]
            for n in xrange(1, size + 1):
                col_name = col_pattern.format(pre=prefix, n=n, suf=suffix)
                columns[col_name] = field_type(*args, **kwargs)
                if "default" in value:
                    defaults[col_name] = value["default"]

        # In order to preserve inheritance, possible overrides, and OEMetaSL's
        # expected behavior, work on a new class that inherits the given bases,
        # then make our model class inherit from this class.
        superclass_name = "_{name}_SuperAnalytic".format(name=name)
        # Set _register to False in order to prevent its instantiation.
        superclass = type(superclass_name, bases, {"_register": False})

        @AddMethod(superclass)
        def fields_get(self, cr, uid, allfields=None, context=None, write_access=True):
            """Override this method to rename analytic fields."""

            res = super(superclass, self).fields_get(
                cr, uid, allfields=allfields, context=context, write_access=write_access
            )

            analytic_osv = self.pool.get("analytic.structure")

            for model_name, prefix, suffix in all_analytic:
                res = analytic_osv.analytic_fields_get(cr, uid, model_name, res, prefix, suffix, context=context)

            return res

        @AddMethod(superclass)
        def fields_view_get(self, cr, uid, view_id=None, view_type="form", context=None, toolbar=False, submenu=False):
            """Override this method to hide unused analytic fields."""

            res = super(superclass, self).fields_view_get(
                cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu
            )

            analytic_osv = self.pool.get("analytic.structure")

            for model_name, prefix, suffix in all_analytic:
                res = analytic_osv.analytic_fields_view_get(cr, uid, model_name, res, prefix, suffix, context=context)

            return res

        return (superclass,)
Пример #21
0
class ir_attachment(osv.osv):

    _inherit = "ir.attachment"

    def _website_url_get(self, cr, uid, ids, name, arg, context=None):
        result = {}
        for attach in self.browse(cr, uid, ids, context=context):
            if attach.url:
                result[attach.id] = attach.url
            else:
                result[attach.id] = self.pool['website'].image_url(
                    cr, uid, attach, 'datas')
        return result

    def _datas_big(self, cr, uid, ids, name, arg, context=None):
        result = dict.fromkeys(ids, False)
        if context and context.get('bin_size'):
            return result

        for record in self.browse(cr, uid, ids, context=context):
            if record.res_model != 'ir.ui.view' or not record.datas: continue
            try:
                result[record.id] = openerp.tools.image_resize_image_big(
                    record.datas)
            except IOError:  # apparently the error PIL.Image.open raises
                pass

        return result

    _columns = {
        'website_url':
        fields.function(_website_url_get, string="Attachment URL",
                        type='char'),
        'datas_big':
        fields.function(_datas_big,
                        type='binary',
                        store=True,
                        string="Resized file content"),
    }

    def try_remove(self, cr, uid, ids, context=None):
        """ Removes a web-based image attachment if it is used by no view
        (template)

        Returns a dict mapping attachments which would not be removed (if any)
        mapped to the views preventing their removal
        """
        Views = self.pool['ir.ui.view']
        attachments_to_remove = []
        # views blocking removal of the attachment
        removal_blocked_by = {}

        for attachment in self.browse(cr, uid, ids, context=context):
            # in-document URLs are html-escaped, a straight search will not
            # find them
            url = escape(attachment.website_url)
            ids = Views.search(cr,
                               uid, [
                                   "|", ('arch_db', 'like', '"%s"' % url),
                                   ('arch_db', 'like', "'%s'" % url)
                               ],
                               context=context)

            if ids:
                removal_blocked_by[attachment.id] = Views.read(cr,
                                                               uid,
                                                               ids, ['name'],
                                                               context=context)
            else:
                attachments_to_remove.append(attachment.id)
        if attachments_to_remove:
            self.unlink(cr, uid, attachments_to_remove, context=context)
        return removal_blocked_by
Пример #22
0
class website(osv.osv):
    def _get_menu(self, cr, uid, ids, name, arg, context=None):
        res = {}
        menu_obj = self.pool.get('website.menu')
        for id in ids:
            menu_ids = menu_obj.search(cr,
                                       uid, [('parent_id', '=', False),
                                             ('website_id', '=', id)],
                                       order='id',
                                       context=context)
            res[id] = menu_ids and menu_ids[0] or False
        return res

    _name = "website"  # Avoid website.website convention for conciseness (for new api). Got a special authorization from xmo and rco
    _description = "Website"
    _columns = {
        'name':
        fields.char('Website Name'),
        'domain':
        fields.char('Website Domain'),
        'company_id':
        fields.many2one('res.company', string="Company"),
        'language_ids':
        fields.many2many('res.lang', 'website_lang_rel', 'website_id',
                         'lang_id', 'Languages'),
        'default_lang_id':
        fields.many2one('res.lang', string="Default language"),
        'default_lang_code':
        fields.related('default_lang_id',
                       'code',
                       type="char",
                       string="Default language code",
                       store=True),
        'social_twitter':
        fields.char('Twitter Account'),
        'social_facebook':
        fields.char('Facebook Account'),
        'social_github':
        fields.char('GitHub Account'),
        'social_linkedin':
        fields.char('LinkedIn Account'),
        'social_youtube':
        fields.char('Youtube Account'),
        'social_googleplus':
        fields.char('Google+ Account'),
        'google_analytics_key':
        fields.char('Google Analytics Key'),
        'user_id':
        fields.many2one('res.users', string='Public User'),
        'compress_html':
        fields.boolean('Compress HTML'),
        'cdn_activated':
        fields.boolean('Activate CDN for assets'),
        'cdn_url':
        fields.char('CDN Base URL'),
        'cdn_filters':
        fields.text(
            'CDN Filters',
            help=
            "URL matching those filters will be rewritten using the CDN Base URL"
        ),
        'partner_id':
        fields.related('user_id',
                       'partner_id',
                       type='many2one',
                       relation='res.partner',
                       string='Public Partner'),
        'menu_id':
        fields.function(_get_menu,
                        relation='website.menu',
                        type='many2one',
                        string='Main Menu')
    }
    _defaults = {
        'user_id':
        lambda self, cr, uid, c: self.pool['ir.model.data'].xmlid_to_res_id(
            cr, openerp.SUPERUSER_ID, 'base.public_user'),
        'company_id':
        lambda self, cr, uid, c: self.pool['ir.model.data'].xmlid_to_res_id(
            cr, openerp.SUPERUSER_ID, 'base.main_company'),
        'compress_html':
        False,
        'cdn_activated':
        False,
        'cdn_url':
        '//localhost:8069/',
        'cdn_filters':
        '\n'.join(DEFAULT_CDN_FILTERS),
    }

    # cf. Wizard hack in website_views.xml
    def noop(self, *args, **kwargs):
        pass

    def write(self, cr, uid, ids, vals, context=None):
        self._get_languages.clear_cache(self)
        return super(website, self).write(cr, uid, ids, vals, context)

    def new_page(self,
                 cr,
                 uid,
                 name,
                 template='website.default_page',
                 ispage=True,
                 context=None):
        context = context or {}
        imd = self.pool.get('ir.model.data')
        view = self.pool.get('ir.ui.view')
        template_module, template_name = template.split('.')

        # completely arbitrary max_length
        page_name = slugify(name, max_length=50)
        page_xmlid = "%s.%s" % (template_module, page_name)

        # find a free xmlid
        inc = 0
        dom = [('key', '=', page_xmlid), '|', ('website_id', '=', False),
               ('website_id', '=', context.get('website_id'))]
        while view.search(cr,
                          openerp.SUPERUSER_ID,
                          dom,
                          context=dict(context or {}, active_test=False)):
            inc += 1
            page_xmlid = "%s.%s" % (template_module, page_name +
                                    (inc and "-%s" % inc or ""))
        page_name += (inc and "-%s" % inc or "")

        # new page
        _, template_id = imd.get_object_reference(cr, uid, template_module,
                                                  template_name)
        website_id = context.get('website_id')
        key = template_module + '.' + page_name
        page_id = view.copy(cr,
                            uid,
                            template_id, {
                                'website_id': website_id,
                                'key': key
                            },
                            context=context)
        page = view.browse(cr, uid, page_id, context=context)
        page.write({
            'arch': page.arch.replace(template, page_xmlid),
            'name': page_name,
            'page': ispage,
        })
        return page_xmlid

    def delete_page(self, cr, uid, view_id, context=None):
        if context is None:
            context = {}
        View = self.pool.get('ir.ui.view')
        view_find = View.search(
            cr,
            uid, [('id', '=', view_id), "|",
                  ('website_id', '=', context.get('website_id')),
                  ('website_id', '=', False), ('page', '=', True),
                  ('type', '=', 'qweb')],
            context=context)
        if view_find:
            View.unlink(cr, uid, view_find, context=context)

    def page_search_dependencies(self, cr, uid, view_id=False, context=None):
        dep = {}
        if not view_id:
            return dep

        # search dependencies just for information.
        # It will not catch 100% of dependencies and False positive is more than possible
        # Each module could add dependences in this dict
        if context is None:
            context = {}
        View = self.pool.get('ir.ui.view')
        Menu = self.pool.get('website.menu')

        view = View.browse(cr, uid, view_id, context=context)
        website_id = context.get('website_id')
        name = view.key.replace("website.", "")
        fullname = "website.%s" % name

        if view.page:
            # search for page with link
            page_search_dom = [
                '|', ('website_id', '=', website_id),
                ('website_id', '=', False), '|',
                ('arch_db', 'ilike', '/page/%s' % name),
                ('arch_db', 'ilike', '/page/%s' % fullname)
            ]
            pages = View.search(cr, uid, page_search_dom, context=context)
            if pages:
                page_key = _('Page')
                dep[page_key] = []
            for page in View.browse(cr, uid, pages, context=context):
                if page.page:
                    dep[page_key].append({
                        'text':
                        _('Page <b>%s</b> seems to have a link to this page !'
                          % page.key),
                        'link':
                        '/page/%s' % page.key
                    })
                else:
                    dep[page_key].append({
                        'text':
                        _('Template <b>%s (id:%s)</b> seems to have a link to this page !'
                          % (page.key, page.id)),
                        'link':
                        '#'
                    })

            # search for menu with link
            menu_search_dom = [
                '|', ('website_id', '=', website_id),
                ('website_id', '=', False), '|',
                ('url', 'ilike', '/page/%s' % name),
                ('url', 'ilike', '/page/%s' % fullname)
            ]

            menus = Menu.search(cr, uid, menu_search_dom, context=context)
            if menus:
                menu_key = _('Menu')
                dep[menu_key] = []
            for menu in Menu.browse(cr, uid, menus, context=context):
                dep[menu_key].append({
                    'text':
                    _('Menu <b>%s</b> seems to have a link to this page !' %
                      menu.name),
                    'link':
                    False
                })

        return dep

    def page_for_name(self,
                      cr,
                      uid,
                      ids,
                      name,
                      module='website',
                      context=None):
        # whatever
        return '%s.%s' % (module, slugify(name, max_length=50))

    def page_exists(self, cr, uid, ids, name, module='website', context=None):
        try:
            name = (name or "").replace("/page/website.",
                                        "").replace("/page/", "")
            if not name:
                return False
            return self.pool["ir.model.data"].get_object_reference(
                cr, uid, module, name)
        except:
            return False

    @openerp.tools.ormcache(skiparg=3)
    def _get_languages(self, cr, uid, id, context=None):
        website = self.browse(cr, uid, id)
        return [(lg.code, lg.name) for lg in website.language_ids]

    def get_cdn_url(self, cr, uid, uri, context=None):
        # Currently only usable in a website_enable request context
        if request and request.website and not request.debug:
            cdn_url = request.website.cdn_url
            cdn_filters = (request.website.cdn_filters or '').splitlines()
            for flt in cdn_filters:
                if flt and re.match(flt, uri):
                    return urlparse.urljoin(cdn_url, uri)
        return uri

    def get_languages(self, cr, uid, ids, context=None):
        return self._get_languages(cr, uid, ids[0], context=context)

    def get_alternate_languages(self, cr, uid, ids, req=None, context=None):
        langs = []
        if req is None:
            req = request.httprequest
        default = self.get_current_website(cr, uid,
                                           context=context).default_lang_code
        uri = req.path
        if req.query_string:
            uri += '?' + req.query_string
        shorts = []
        for code, name in self.get_languages(cr, uid, ids, context=context):
            lg_path = ('/' + code) if code != default else ''
            lg = code.split('_')
            shorts.append(lg[0])
            lang = {
                'hreflang': ('-'.join(lg)).lower(),
                'short': lg[0],
                'href': req.url_root[0:-1] + lg_path + uri,
            }
            langs.append(lang)
        for lang in langs:
            if shorts.count(lang['short']) == 1:
                lang['hreflang'] = lang['short']
        return langs

    @openerp.tools.ormcache(skiparg=4)
    def _get_current_website_id(self, cr, uid, domain_name, context=None):
        ids = self.search(cr,
                          uid, [('name', '=', domain_name)],
                          limit=1,
                          context=context)
        if ids:
            return ids[0]
        else:
            return self.search(cr, uid, [], limit=1, context=context)[0]

    def get_current_website(self, cr, uid, context=None):
        domain_name = request.httprequest.environ.get('HTTP_HOST',
                                                      '').split(':')[0]
        website_id = self._get_current_website_id(cr,
                                                  uid,
                                                  domain_name,
                                                  context=context)
        request.context['website_id'] = website_id
        return self.browse(cr, uid, website_id, context=context)

    def is_publisher(self, cr, uid, ids, context=None):
        Access = self.pool['ir.model.access']
        is_website_publisher = Access.check(cr,
                                            uid,
                                            'ir.ui.view',
                                            'write',
                                            False,
                                            context=context)
        return is_website_publisher

    def is_user(self, cr, uid, ids, context=None):
        Access = self.pool['ir.model.access']
        return Access.check(cr,
                            uid,
                            'ir.ui.menu',
                            'read',
                            False,
                            context=context)

    def get_template(self, cr, uid, ids, template, context=None):
        if not isinstance(template, (int, long)) and '.' not in template:
            template = 'website.%s' % template
        View = self.pool['ir.ui.view']
        view_id = View.get_view_id(cr, uid, template, context=context)
        if not view_id:
            raise NotFound
        return View.browse(cr, uid, view_id, context=context)

    def _render(self, cr, uid, ids, template, values=None, context=None):
        # TODO: remove this. (just kept for backward api compatibility for saas-3)
        return self.pool['ir.ui.view'].render(cr,
                                              uid,
                                              template,
                                              values=values,
                                              context=context)

    def render(self,
               cr,
               uid,
               ids,
               template,
               values=None,
               status_code=None,
               context=None):
        # TODO: remove this. (just kept for backward api compatibility for saas-3)
        return request.render(template, values, uid=uid)

    def pager(self,
              cr,
              uid,
              ids,
              url,
              total,
              page=1,
              step=30,
              scope=5,
              url_args=None,
              context=None):
        # Compute Pager
        page_count = int(math.ceil(float(total) / step))

        page = max(1, min(int(page if str(page).isdigit() else 1), page_count))
        scope -= 1

        pmin = max(page - int(math.floor(scope / 2)), 1)
        pmax = min(pmin + scope, page_count)

        if pmax - pmin < scope:
            pmin = pmax - scope if pmax - scope > 0 else 1

        def get_url(page):
            _url = "%s/page/%s" % (url, page) if page > 1 else url
            if url_args:
                _url = "%s?%s" % (_url, werkzeug.url_encode(url_args))
            return _url

        return {
            "page_count":
            page_count,
            "offset": (page - 1) * step,
            "page": {
                'url': get_url(page),
                'num': page
            },
            "page_start": {
                'url': get_url(pmin),
                'num': pmin
            },
            "page_previous": {
                'url': get_url(max(pmin, page - 1)),
                'num': max(pmin, page - 1)
            },
            "page_next": {
                'url': get_url(min(pmax, page + 1)),
                'num': min(pmax, page + 1)
            },
            "page_end": {
                'url': get_url(pmax),
                'num': pmax
            },
            "pages": [{
                'url': get_url(page),
                'num': page
            } for page in xrange(pmin, pmax + 1)]
        }

    def rule_is_enumerable(self, rule):
        """ Checks that it is possible to generate sensible GET queries for
        a given rule (if the endpoint matches its own requirements)

        :type rule: werkzeug.routing.Rule
        :rtype: bool
        """
        endpoint = rule.endpoint
        methods = rule.methods or ['GET']
        converters = rule._converters.values()
        if not ('GET' in methods and endpoint.routing['type'] == 'http'
                and endpoint.routing['auth'] in ('none', 'public')
                and endpoint.routing.get('website', False) and all(
                    hasattr(converter, 'generate') for converter in converters)
                and endpoint.routing.get('website')):
            return False

        # dont't list routes without argument having no default value or converter
        spec = inspect.getargspec(endpoint.method.original_func)

        # remove self and arguments having a default value
        defaults_count = len(spec.defaults or [])
        args = spec.args[1:(-defaults_count or None)]

        # check that all args have a converter
        return all((arg in rule._converters) for arg in args)

    def enumerate_pages(self, cr, uid, ids, query_string=None, context=None):
        """ Available pages in the website/CMS. This is mostly used for links
        generation and can be overridden by modules setting up new HTML
        controllers for dynamic pages (e.g. blog).

        By default, returns template views marked as pages.

        :param str query_string: a (user-provided) string, fetches pages
                                 matching the string
        :returns: a list of mappings with two keys: ``name`` is the displayable
                  name of the resource (page), ``url`` is the absolute URL
                  of the same.
        :rtype: list({name: str, url: str})
        """
        router = request.httprequest.app.get_db_router(request.db)
        # Force enumeration to be performed as public user
        url_list = []
        for rule in router.iter_rules():
            if not self.rule_is_enumerable(rule):
                continue

            converters = rule._converters or {}
            if query_string and not converters and (
                    query_string not in rule.build([{}],
                                                   append_unknown=False)[1]):
                continue
            values = [{}]
            convitems = converters.items()
            # converters with a domain are processed after the other ones
            gd = lambda x: hasattr(x[1], 'domain') and (x[1].domain <> '[]')
            convitems.sort(lambda x, y: cmp(gd(x), gd(y)))
            for (i, (name, converter)) in enumerate(convitems):
                newval = []
                for val in values:
                    query = i == (len(convitems) - 1) and query_string
                    for v in converter.generate(request.cr,
                                                uid,
                                                query=query,
                                                args=val,
                                                context=context):
                        newval.append(val.copy())
                        v[name] = v['loc']
                        del v['loc']
                        newval[-1].update(v)
                values = newval

            for value in values:
                domain_part, url = rule.build(value, append_unknown=False)
                page = {'loc': url}
                for key, val in value.items():
                    if key.startswith('__'):
                        page[key[2:]] = val
                if url in ('/sitemap.xml', ):
                    continue
                if url in url_list:
                    continue
                url_list.append(url)

                yield page

    def search_pages(self,
                     cr,
                     uid,
                     ids,
                     needle=None,
                     limit=None,
                     context=None):
        name = re.sub(r"^/p(a(g(e(/(w(e(b(s(i(t(e(\.)?)?)?)?)?)?)?)?)?)?)?)?",
                      "", needle or "")
        res = []
        for page in self.enumerate_pages(cr,
                                         uid,
                                         ids,
                                         query_string=name,
                                         context=context):
            if needle in page['loc']:
                res.append(page)
                if len(res) == limit:
                    break
        return res

    def kanban(self,
               cr,
               uid,
               ids,
               model,
               domain,
               column,
               template,
               step=None,
               scope=None,
               orderby=None,
               context=None):
        step = step and int(step) or 10
        scope = scope and int(scope) or 5
        orderby = orderby or "name"

        get_args = dict(request.httprequest.args or {})
        model_obj = self.pool[model]
        relation = model_obj._columns.get(column)._obj
        relation_obj = self.pool[relation]

        get_args.setdefault('kanban', "")
        kanban = get_args.pop('kanban')
        kanban_url = "?%s&kanban=" % werkzeug.url_encode(get_args)

        pages = {}
        for col in kanban.split(","):
            if col:
                col = col.split("-")
                pages[int(col[0])] = int(col[1])

        objects = []
        for group in model_obj.read_group(cr,
                                          uid,
                                          domain, ["id", column],
                                          groupby=column):
            obj = {}

            # browse column
            relation_id = group[column][0]
            obj['column_id'] = relation_obj.browse(cr, uid, relation_id)

            obj['kanban_url'] = kanban_url
            for k, v in pages.items():
                if k != relation_id:
                    obj['kanban_url'] += "%s-%s" % (k, v)

            # pager
            number = model_obj.search(cr, uid, group['__domain'], count=True)
            obj['page_count'] = int(math.ceil(float(number) / step))
            obj['page'] = pages.get(relation_id) or 1
            if obj['page'] > obj['page_count']:
                obj['page'] = obj['page_count']
            offset = (obj['page'] - 1) * step
            obj['page_start'] = max(
                obj['page'] - int(math.floor((scope - 1) / 2)), 1)
            obj['page_end'] = min(obj['page_start'] + (scope - 1),
                                  obj['page_count'])

            # view data
            obj['domain'] = group['__domain']
            obj['model'] = model
            obj['step'] = step
            obj['orderby'] = orderby

            # browse objects
            object_ids = model_obj.search(cr,
                                          uid,
                                          group['__domain'],
                                          limit=step,
                                          offset=offset,
                                          order=orderby)
            obj['object_ids'] = model_obj.browse(cr, uid, object_ids)

            objects.append(obj)

        values = {
            'objects': objects,
            'range': range,
            'template': template,
        }
        return request.website._render("website.kanban_contain", values)

    def kanban_col(self,
                   cr,
                   uid,
                   ids,
                   model,
                   domain,
                   page,
                   template,
                   step,
                   orderby,
                   context=None):
        html = ""
        model_obj = self.pool[model]
        domain = safe_eval(domain)
        step = int(step)
        offset = (int(page) - 1) * step
        object_ids = model_obj.search(cr,
                                      uid,
                                      domain,
                                      limit=step,
                                      offset=offset,
                                      order=orderby)
        object_ids = model_obj.browse(cr, uid, object_ids)
        for object_id in object_ids:
            html += request.website._render(template, {'object_id': object_id})
        return html

    def _image_placeholder(self, response):
        # file_open may return a StringIO. StringIO can be closed but are
        # not context managers in Python 2 though that is fixed in 3
        with contextlib.closing(
                openerp.tools.misc.file_open(os.path.join(
                    'web', 'static', 'src', 'img', 'placeholder.png'),
                                             mode='rb')) as f:
            response.data = f.read()
            return response.make_conditional(request.httprequest)

    def _image(self,
               cr,
               uid,
               model,
               id,
               field,
               response,
               max_width=maxint,
               max_height=maxint,
               cache=None,
               context=None):
        """ Fetches the requested field and ensures it does not go above
        (max_width, max_height), resizing it if necessary.

        Resizing is bypassed if the object provides a $field_big, which will
        be interpreted as a pre-resized version of the base field.

        If the record is not found or does not have the requested field,
        returns a placeholder image via :meth:`~._image_placeholder`.

        Sets and checks conditional response parameters:
        * :mailheader:`ETag` is always set (and checked)
        * :mailheader:`Last-Modified is set iif the record has a concurrency
          field (``__last_update``)

        The requested field is assumed to be base64-encoded image data in
        all cases.
        """
        Model = self.pool[model]
        id = int(id)

        ids = Model.search(cr, uid, [('id', '=', id)], context=context)
        if not ids and 'website_published' in Model._fields:
            ids = Model.search(cr,
                               openerp.SUPERUSER_ID,
                               [('id', '=', id),
                                ('website_published', '=', True)],
                               context=context)
        if not ids:
            return self._image_placeholder(response)

        concurrency = '__last_update'
        [record] = Model.read(cr,
                              openerp.SUPERUSER_ID, [id], [concurrency, field],
                              context=context)

        if concurrency in record:
            server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
            try:
                response.last_modified = datetime.datetime.strptime(
                    record[concurrency], server_format + '.%f')
            except ValueError:
                # just in case we have a timestamp without microseconds
                response.last_modified = datetime.datetime.strptime(
                    record[concurrency], server_format)

        # Field does not exist on model or field set to False
        if not record.get(field):
            # FIXME: maybe a field which does not exist should be a 404?
            return self._image_placeholder(response)

        response.set_etag(hashlib.sha1(record[field]).hexdigest())
        response.make_conditional(request.httprequest)

        if cache:
            response.cache_control.max_age = cache
            response.expires = int(time.time() + cache)

        # conditional request match
        if response.status_code == 304:
            return response

        if model == 'ir.attachment' and field == 'url' and field in record:
            path = record[field].strip('/')

            # Check that we serve a file from within the module
            if os.path.normpath(path).startswith('..'):
                return self._image_placeholder(response)

            # Check that the file actually exists
            path = path.split('/')
            resource = openerp.modules.get_module_resource(*path)
            if not resource:
                return self._image_placeholder(response)

            data = open(resource, 'rb').read()
        else:
            data = record[field].decode('base64')
        image = Image.open(cStringIO.StringIO(data))
        response.mimetype = Image.MIME[image.format]

        filename = '%s_%s.%s' % (model.replace('.', '_'), id, str(
            image.format).lower())
        response.headers[
            'Content-Disposition'] = 'inline; filename="%s"' % filename

        if (not max_width) and (not max_height):
            response.data = data
            return response

        w, h = image.size
        max_w = int(max_width) if max_width else maxint
        max_h = int(max_height) if max_height else maxint

        if w < max_w and h < max_h:
            response.data = data
        else:
            size = (max_w, max_h)
            img = image_resize_and_sharpen(image,
                                           size,
                                           preserve_aspect_ratio=True)
            image_save_for_web(img, response.stream, format=image.format)
            # invalidate content-length computed by make_conditional as
            # writing to response.stream does not do it (as of werkzeug 0.9.3)
            del response.headers['Content-Length']

        return response

    def image_url(self, cr, uid, record, field, size=None, context=None):
        """Returns a local url that points to the image field of a given browse record."""
        model = record._name
        sudo_record = record.sudo()
        id = '%s_%s' % (record.id,
                        hashlib.sha1(sudo_record.write_date
                                     or sudo_record.create_date
                                     or '').hexdigest()[0:7])
        size = '' if size is None else '/%s' % size
        return '/website/image/%s/%s/%s%s' % (model, id, field, size)
Пример #23
0
#            ('confirm', 'Waiting Approval'),   = deducted in budget
#            ('accepted', 'Approved'),          = deducted in budget
#            ('done', 'Waiting Payment'),       = deducted in budget 
#            ('paid', 'Paid'),                  = deducted in budget + cash
            
#Totals
            res[company.id]['smart_cash'] = round(res[company.id]['smart_cash'] - res[company.id]['smart_amount_cash'],0)
            res[company.id]['smart_budget'] = round(res[company.id]['smart_budget']  - res[company.id]['smart_amount_budget'],0)

            
                 
            #res[company.id]['smart_cash'] = 0.0
        return res

    _columns = {
       'smart_budget': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Budget',multi='all',help="Approved invoiced amount.",),
#       'smart_cash': fields.function(smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Budget',
#            help="Approved invoiced amount.",
#            multi='all',),
       'smart_cash': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Cash',
            help="Free invoiced amount for salary or expenses.",
            multi='all',),
        'prepayment': fields.boolean('Prepayment',help="SMart User: this virtual company can have prepayment smart_cash, SMart Company: this country applies prepayment"),
        'prepayment_days': fields.integer('Prepayment Days',help="Leadtime in days before invoiced amount becomes smart_cash (global)"),
        'smart_share': fields.float('SMarts Share',digits_compute=dp.get_precision('Account')),
        'sale_order_sum_cash': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Order sum cash',multi='all',help="Approved invoiced amount.",),
        'sale_order_sum_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Order sum budget',multi='all',help="Approved invoiced amount.",),
        'smart_amount_cash':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Amount cash',multi='all',help="Approved invoiced amount.",),
        'smart_amount_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Amount budget',multi='all',help="Approved invoiced amount.",),
        'activity_amount_cash':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart activity amount cash',multi='all',help="Approved invoiced amount.",),
        'activity_amount_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart activity amount budget',multi='all',help="Approved invoiced amount.",),
Пример #24
0
class note_note(osv.osv):
    """ Note """
    _name = 'note.note'
    _inherit = ['mail.thread']
    _description = "Note"

    #writing method (no modification of values)
    def name_create(self, cr, uid, name, context=None):
        rec_id = self.create(cr, uid, {'memo': name}, context=context)
        return self.name_get(cr, uid, [rec_id], context)[0]

    #read the first line (convert hml into text)
    def _get_note_first_line(self, cr, uid, ids, name="", args={}, context=None):
        res = {}
        for note in self.browse(cr, uid, ids, context=context):
            res[note.id] = (note.memo and html2plaintext(note.memo) or "").strip().replace('*','').split("\n")[0]

        return res

    def onclick_note_is_done(self, cr, uid, ids, context=None):
        return self.write(cr, uid, ids, {'open': False, 'date_done': fields.date.today()}, context=context)

    def onclick_note_not_done(self, cr, uid, ids, context=None):
        return self.write(cr, uid, ids, {'open': True}, context=context)

    #return the default stage for the uid user
    def _get_default_stage_id(self,cr,uid,context=None):
        ids = self.pool.get('note.stage').search(cr,uid,[('user_id','=',uid)], context=context)
        return ids and ids[0] or False

    def _set_stage_per_user(self, cr, uid, id, name, value, args=None, context=None):
        note = self.browse(cr, uid, id, context=context)
        if not value: return False
        stage_ids = [value] + [stage.id for stage in note.stage_ids if stage.user_id.id != uid ]
        return self.write(cr, uid, [id], {'stage_ids': [(6, 0, set(stage_ids))]}, context=context)

    def _get_stage_per_user(self, cr, uid, ids, name, args, context=None):
        result = dict.fromkeys(ids, False)
        for record in self.browse(cr, uid, ids, context=context):
            for stage in record.stage_ids:
                if stage.user_id.id == uid:
                    result[record.id] = stage.id
        return result

    _columns = {
        'name': fields.function(_get_note_first_line, 
            string='Note Summary', 
            type='text', store=True),
        'user_id': fields.many2one('res.users', 'Owner'),
        'memo': fields.html('Note Content'),
        'sequence': fields.integer('Sequence'),
        'stage_id': fields.function(_get_stage_per_user, 
            fnct_inv=_set_stage_per_user, 
            string='Stage', 
            type='many2one', 
            relation='note.stage'),
        'stage_ids': fields.many2many('note.stage','note_stage_rel','note_id','stage_id','Stages of Users'),
        'open': fields.boolean('Active', track_visibility='onchange'),
        'date_done': fields.date('Date done'),
        'color': fields.integer('Color Index'),
        'tag_ids' : fields.many2many('note.tag','note_tags_rel','note_id','tag_id','Tags'),
    }
    _defaults = {
        'user_id': lambda self, cr, uid, ctx=None: uid,
        'open' : 1,
        'stage_id' : _get_default_stage_id,
    }
    _order = 'sequence'

    def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True):
        if groupby and groupby[0]=="stage_id":

            #search all stages
            current_stage_ids = self.pool.get('note.stage').search(cr,uid,[('user_id','=',uid)], context=context)

            if current_stage_ids: #if the user have some stages

                #dict of stages: map les ids sur les noms
                stage_name = dict(self.pool.get('note.stage').name_get(cr, uid, current_stage_ids, context=context))

                result = [{ #notes by stage for stages user
                        '__context': {'group_by': groupby[1:]},
                        '__domain': domain + [('stage_ids.id', '=', current_stage_id)],
                        'stage_id': (current_stage_id, stage_name[current_stage_id]),
                        'stage_id_count': self.search(cr,uid, domain+[('stage_ids', '=', current_stage_id)], context=context, count=True)
                    } for current_stage_id in current_stage_ids]

                #note without user's stage
                nb_notes_ws = self.search(cr,uid, domain+[('stage_ids', 'not in', current_stage_ids)], context=context, count=True)
                if nb_notes_ws:
                    # add note to the first column if it's the first stage
                    dom_not_in = ('stage_ids', 'not in', current_stage_ids)
                    if result and result[0]['stage_id'][0] == current_stage_ids[0]:
                        dom_in = result[0]['__domain'].pop()
                        result[0]['__domain'] = domain + ['|', dom_in, dom_not_in]
                        result[0]['stage_id_count'] += nb_notes_ws
                    else:
                        # add the first stage column
                        result = [{
                            '__context': {'group_by': groupby[1:]},
                            '__domain': domain + [dom_not_in],
                            'stage_id': (current_stage_ids[0], stage_name[current_stage_ids[0]]),
                            'stage_id_count':nb_notes_ws
                        }] + result

            else: # if stage_ids is empty

                #note without user's stage
                nb_notes_ws = self.search(cr,uid, domain, context=context, count=True)
                if nb_notes_ws:
                    result = [{ #notes for unknown stage
                        '__context': {'group_by': groupby[1:]},
                        '__domain': domain,
                        'stage_id': False,
                        'stage_id_count':nb_notes_ws
                    }]
                else:
                    result = []
            return result

        else:
            return super(note_note, self).read_group(self, cr, uid, domain, fields, groupby, 
                offset=offset, limit=limit, context=context, orderby=orderby,lazy=lazy)
Пример #25
0
    def _datas_big(self, cr, uid, ids, name, arg, context=None):
        result = dict.fromkeys(ids, False)
        if context and context.get('bin_size'):
            return result

        for record in self.browse(cr, uid, ids, context=context):
            if record.res_model != 'ir.ui.view' or not record.datas: continue
            try:
                result[record.id] = openerp.tools.image_resize_image_big(record.datas)
            except Exception,ex:  # ignore any f*****g exceptions
                pass

        return result

    _columns = {
        'datas_checksum': fields.function(_datas_checksum, size=40,
              string="Datas checksum", type='char', store=True, select=True),
        'website_url': fields.function(_website_url_get, string="Attachment URL", type='char'),
        'datas_big': fields.function (_datas_big, type='binary', store=True,
                                      string="Resized file content"),
        'mimetype': fields.char('Mime Type', readonly=True),
    }

    def _add_mimetype_if_needed(self, values):
        if values.get('datas_fname'):
            values['mimetype'] = mimetypes.guess_type(values.get('datas_fname'))[0] or 'application/octet-stream'

    def create(self, cr, uid, values, context=None):
        chk = self._compute_checksum(values)
        if chk:
            match = self.search(cr, uid, [('datas_checksum', '=', chk)], context=context)
            if match:
Пример #26
0
class sale_order(osv.osv):
    _inherit = "sale.order"

    def _get_default_warehouse(self, cr, uid, context=None):
        company_id = self.pool.get('res.users')._get_company(cr,
                                                             uid,
                                                             context=context)
        warehouse_ids = self.pool.get('stock.warehouse').search(
            cr, uid, [('company_id', '=', company_id)], context=context)
        if not warehouse_ids:
            return False
        return warehouse_ids[0]

    def _get_shipped(self, cr, uid, ids, name, args, context=None):
        res = {}
        for sale in self.browse(cr, uid, ids, context=context):
            group = sale.procurement_group_id
            if group:
                res[sale.id] = all([
                    proc.state in ['cancel', 'done']
                    for proc in group.procurement_ids
                ])
            else:
                res[sale.id] = False
        return res

    def _get_orders(self, cr, uid, ids, context=None):
        res = set()
        for move in self.browse(cr, uid, ids, context=context):
            if move.procurement_id and move.procurement_id.sale_line_id:
                res.add(move.procurement_id.sale_line_id.order_id.id)
        return list(res)

    def _get_orders_procurements(self, cr, uid, ids, context=None):
        res = set()
        for proc in self.pool.get('procurement.order').browse(cr,
                                                              uid,
                                                              ids,
                                                              context=context):
            if proc.state == 'done' and proc.sale_line_id:
                res.add(proc.sale_line_id.order_id.id)
        return list(res)

    def _get_picking_ids(self, cr, uid, ids, name, args, context=None):
        res = {}
        for sale in self.browse(cr, uid, ids, context=context):
            if not sale.procurement_group_id:
                res[sale.id] = []
                continue
            res[sale.id] = self.pool.get('stock.picking').search(
                cr,
                uid, [('group_id', '=', sale.procurement_group_id.id)],
                context=context)
        return res

    def _prepare_order_line_procurement(self,
                                        cr,
                                        uid,
                                        order,
                                        line,
                                        group_id=False,
                                        context=None):
        vals = super(sale_order,
                     self)._prepare_order_line_procurement(cr,
                                                           uid,
                                                           order,
                                                           line,
                                                           group_id=group_id,
                                                           context=context)
        location_id = order.partner_shipping_id.property_stock_customer.id
        vals['location_id'] = location_id
        routes = line.route_id and [(4, line.route_id.id)] or []
        vals['route_ids'] = routes
        vals[
            'warehouse_id'] = order.warehouse_id and order.warehouse_id.id or False
        vals['partner_dest_id'] = order.partner_shipping_id.id
        return vals

    _columns = {
        'incoterm':
        fields.many2one(
            'stock.incoterms',
            'Incoterm',
            help=
            "International Commercial Terms are a series of predefined commercial terms used in international transactions."
        ),
        'picking_policy':
        fields.selection(
            [('direct', 'Deliver each product when available'),
             ('one', 'Deliver all products at once')],
            'Shipping Policy',
            required=True,
            readonly=True,
            states={
                'draft': [('readonly', False)],
                'sent': [('readonly', False)]
            },
            help=
            """Pick 'Deliver each product when available' if you allow partial delivery."""
        ),
        'order_policy':
        fields.selection(
            [
                ('manual', 'On Demand'),
                ('picking', 'On Delivery Order'),
                ('prepaid', 'Before Delivery'),
            ],
            'Create Invoice',
            required=True,
            readonly=True,
            states={
                'draft': [('readonly', False)],
                'sent': [('readonly', False)]
            },
            help=
            """On demand: A draft invoice can be created from the sales order when needed. \nOn delivery order: A draft invoice can be created from the delivery order when the products have been delivered. \nBefore delivery: A draft invoice is created from the sales order and must be paid before the products can be delivered."""
        ),
        'shipped':
        fields.function(_get_shipped,
                        string='Delivered',
                        type='boolean',
                        store={
                            'procurement.order':
                            (_get_orders_procurements, ['state'], 10)
                        }),
        'warehouse_id':
        fields.many2one('stock.warehouse', 'Warehouse', required=True),
        'picking_ids':
        fields.function(_get_picking_ids,
                        method=True,
                        type='one2many',
                        relation='stock.picking',
                        string='Picking associated to this sale'),
    }
    _defaults = {
        'warehouse_id': _get_default_warehouse,
        'picking_policy': 'direct',
        'order_policy': 'manual',
    }

    def onchange_warehouse_id(self, cr, uid, ids, warehouse_id, context=None):
        val = {}
        if warehouse_id:
            warehouse = self.pool.get('stock.warehouse').browse(
                cr, uid, warehouse_id, context=context)
            if warehouse.company_id:
                val['company_id'] = warehouse.company_id.id
        return {'value': val}

    def action_view_delivery(self, cr, uid, ids, context=None):
        '''
        This function returns an action that display existing delivery orders
        of given sales order ids. It can either be a in a list or in a form
        view, if there is only one delivery order to show.
        '''

        mod_obj = self.pool.get('ir.model.data')
        act_obj = self.pool.get('ir.actions.act_window')

        result = mod_obj.get_object_reference(cr, uid, 'stock',
                                              'action_picking_tree_all')
        id = result and result[1] or False
        result = act_obj.read(cr, uid, [id], context=context)[0]

        #compute the number of delivery orders to display
        pick_ids = []
        for so in self.browse(cr, uid, ids, context=context):
            pick_ids += [picking.id for picking in so.picking_ids]

        #choose the view_mode accordingly
        if len(pick_ids) > 1:
            result['domain'] = "[('id','in',[" + ','.join(map(
                str, pick_ids)) + "])]"
        else:
            res = mod_obj.get_object_reference(cr, uid, 'stock',
                                               'view_picking_form')
            result['views'] = [(res and res[1] or False, 'form')]
            result['res_id'] = pick_ids and pick_ids[0] or False
        return result

    def action_invoice_create(self,
                              cr,
                              uid,
                              ids,
                              grouped=False,
                              states=['confirmed', 'done', 'exception'],
                              date_invoice=False,
                              context=None):
        move_obj = self.pool.get("stock.move")
        res = super(sale_order,
                    self).action_invoice_create(cr,
                                                uid,
                                                ids,
                                                grouped=grouped,
                                                states=states,
                                                date_invoice=date_invoice,
                                                context=context)
        for order in self.browse(cr, uid, ids, context=context):
            if order.order_policy == 'picking':
                for picking in order.picking_ids:
                    move_obj.write(cr,
                                   uid, [x.id for x in picking.move_lines],
                                   {'invoice_state': 'invoiced'},
                                   context=context)
        return res

    def action_cancel(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        sale_order_line_obj = self.pool.get('sale.order.line')
        proc_obj = self.pool.get('procurement.order')
        stock_obj = self.pool.get('stock.picking')
        for sale in self.browse(cr, uid, ids, context=context):
            for pick in sale.picking_ids:
                if pick.state not in ('draft', 'cancel'):
                    raise osv.except_osv(
                        _('Cannot cancel sales order!'),
                        _('You must first cancel all delivery order(s) attached to this sales order.'
                          ))
            stock_obj.signal_workflow(cr, uid,
                                      [p.id for p in sale.picking_ids],
                                      'button_cancel')
        return super(sale_order, self).action_cancel(cr,
                                                     uid,
                                                     ids,
                                                     context=context)

    def action_wait(self, cr, uid, ids, context=None):
        res = super(sale_order, self).action_wait(cr,
                                                  uid,
                                                  ids,
                                                  context=context)
        for o in self.browse(cr, uid, ids):
            noprod = self.test_no_product(cr, uid, o, context)
            if noprod and o.order_policy == 'picking':
                self.write(cr,
                           uid, [o.id], {'order_policy': 'manual'},
                           context=context)
        return res

    def _get_date_planned(self,
                          cr,
                          uid,
                          order,
                          line,
                          start_date,
                          context=None):
        date_planned = super(sale_order,
                             self)._get_date_planned(cr,
                                                     uid,
                                                     order,
                                                     line,
                                                     start_date,
                                                     context=context)
        date_planned = (date_planned -
                        timedelta(days=order.company_id.security_lead)
                        ).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
        return date_planned

    def _prepare_procurement_group(self, cr, uid, order, context=None):
        res = super(sale_order, self)._prepare_procurement_group(cr,
                                                                 uid,
                                                                 order,
                                                                 context=None)
        res.update({'move_type': order.picking_policy})
        return res

    def action_ship_end(self, cr, uid, ids, context=None):
        super(sale_order, self).action_ship_end(cr, uid, ids, context=context)
        for order in self.browse(cr, uid, ids, context=context):
            val = {'shipped': True}
            if order.state == 'shipping_except':
                val['state'] = 'progress'
                if (order.order_policy == 'manual'):
                    for line in order.order_line:
                        if (not line.invoiced) and (line.state
                                                    not in ('cancel',
                                                            'draft')):
                            val['state'] = 'manual'
                            break
            res = self.write(cr, uid, [order.id], val)
        return True

    def has_stockable_products(self, cr, uid, ids, *args):
        for order in self.browse(cr, uid, ids):
            for order_line in order.order_line:
                if order_line.product_id and order_line.product_id.type in (
                        'product', 'consu'):
                    return True
        return False
Пример #27
0

class hr_employee(orm.Model):
    _description = "Employee"
    _inherit = 'hr.employee'

    def _get_assigned_letters(self, cr, uid, ids, prop, unknow_none, context=None):
        if not len(ids):
            return {}
        model_name = super(hr_employee, self)._name
        res = []
        try:
            for id in ids:
                letter_ids = []
                ref_ids = self.pool['letter.ref'].search(cr, uid, [('int_ref', '=', model_name + ',' + str(id))],
                                                         context=context)
                if ref_ids:
                    for ref in self.pool['letter.ref'].read(cr, uid, ref_ids, context=context):
                        letter_ids.append(ref['letter_id'][0])
                res.append((id, letter_ids))
        except Exception, e:
            _logger.error(repr(traceback.extract_tb(sys.exc_traceback)))

        return dict(res)

    _columns = {
        'letter_ids': fields.function(_get_assigned_letters, method=True, string='Letter', type='one2many',
                                      relation="res.letter"),
    }

Пример #28
0
class sale_order_line(osv.osv):
    _inherit = 'sale.order.line'

    def _number_packages(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            try:
                res[line.id] = int(
                    (line.product_uom_qty + line.product_packaging.qty -
                     0.0001) / line.product_packaging.qty)
            except:
                res[line.id] = 1
        return res

    _columns = {
        'product_packaging':
        fields.many2one('product.packaging', 'Packaging'),
        'number_packages':
        fields.function(_number_packages,
                        type='integer',
                        string='Number Packages'),
        'route_id':
        fields.many2one('stock.location.route',
                        'Route',
                        domain=[('sale_selectable', '=', True)]),
    }

    _defaults = {
        'product_packaging': False,
    }

    def product_packaging_change(self,
                                 cr,
                                 uid,
                                 ids,
                                 pricelist,
                                 product,
                                 qty=0,
                                 uom=False,
                                 partner_id=False,
                                 packaging=False,
                                 flag=False,
                                 context=None):
        if not product:
            return {'value': {'product_packaging': False}}
        product_obj = self.pool.get('product.product')
        product_uom_obj = self.pool.get('product.uom')
        pack_obj = self.pool.get('product.packaging')
        warning = {}
        result = {}
        warning_msgs = ''
        if flag:
            res = self.product_id_change(cr,
                                         uid,
                                         ids,
                                         pricelist=pricelist,
                                         product=product,
                                         qty=qty,
                                         uom=uom,
                                         partner_id=partner_id,
                                         packaging=packaging,
                                         flag=False,
                                         context=context)
            warning_msgs = res.get('warning') and res['warning'].get(
                'message', '') or ''

        products = product_obj.browse(cr, uid, product, context=context)
        if not products.packaging_ids:
            packaging = result['product_packaging'] = False

        if packaging:
            default_uom = products.uom_id and products.uom_id.id
            pack = pack_obj.browse(cr, uid, packaging, context=context)
            q = product_uom_obj._compute_qty(cr, uid, uom, pack.qty,
                                             default_uom)
            #            qty = qty - qty % q + q
            if qty and (q and not (qty % q) == 0):
                ean = pack.ean or _('(n/a)')
                qty_pack = pack.qty
                type_ul = pack.ul
                if not warning_msgs:
                    warn_msg = _("You selected a quantity of %d Units.\n"
                                "But it's not compatible with the selected packaging.\n"
                                "Here is a proposition of quantities according to the packaging:\n"
                                "EAN: %s Quantity: %s Type of ul: %s") % \
                                    (qty, ean, qty_pack, type_ul.name)
                    warning_msgs += _(
                        "Picking Information ! : ") + warn_msg + "\n\n"
                warning = {
                    'title': _('Configuration Error!'),
                    'message': warning_msgs
                }
            result['product_uom_qty'] = qty

        return {'value': result, 'warning': warning}

    def product_id_change_with_wh(self,
                                  cr,
                                  uid,
                                  ids,
                                  pricelist,
                                  product,
                                  qty=0,
                                  uom=False,
                                  qty_uos=0,
                                  uos=False,
                                  name='',
                                  partner_id=False,
                                  lang=False,
                                  update_tax=True,
                                  date_order=False,
                                  packaging=False,
                                  fiscal_position=False,
                                  flag=False,
                                  warehouse_id=False,
                                  context=None):
        context = context or {}
        product_uom_obj = self.pool.get('product.uom')
        product_obj = self.pool.get('product.product')
        warning = {}
        res = self.product_id_change(cr,
                                     uid,
                                     ids,
                                     pricelist,
                                     product,
                                     qty=qty,
                                     uom=uom,
                                     qty_uos=qty_uos,
                                     uos=uos,
                                     name=name,
                                     partner_id=partner_id,
                                     lang=lang,
                                     update_tax=update_tax,
                                     date_order=date_order,
                                     packaging=packaging,
                                     fiscal_position=fiscal_position,
                                     flag=flag,
                                     context=context)

        if not product:
            res['value'].update({'product_packaging': False})
            return res

        #update of result obtained in super function
        product_obj = product_obj.browse(cr, uid, product, context=context)
        res['value']['delay'] = (product_obj.sale_delay or 0.0)

        # Calling product_packaging_change function after updating UoM
        res_packing = self.product_packaging_change(cr,
                                                    uid,
                                                    ids,
                                                    pricelist,
                                                    product,
                                                    qty,
                                                    uom,
                                                    partner_id,
                                                    packaging,
                                                    context=context)
        res['value'].update(res_packing.get('value', {}))
        warning_msgs = res_packing.get(
            'warning') and res_packing['warning']['message'] or ''

        if product_obj.type == 'product':
            #determine if the product is MTO or not (for a further check)
            isMto = False
            if warehouse_id:
                warehouse = self.pool.get('stock.warehouse').browse(
                    cr, uid, warehouse_id, context=context)
                for product_route in product_obj.route_ids:
                    if warehouse.mto_pull_id and warehouse.mto_pull_id.route_id and warehouse.mto_pull_id.route_id.id == product_route.id:
                        isMto = True
                        break
            else:
                try:
                    mto_route_id = self.pool.get('ir.model.data').get_object(
                        cr, uid, 'stock', 'route_warehouse0_mto').id
                except:
                    # if route MTO not found in ir_model_data, we treat the product as in MTS
                    mto_route_id = False
                if mto_route_id:
                    for product_route in product_obj.route_ids:
                        if product_route.id == mto_route_id:
                            isMto = True
                            break

            #check if product is available, and if not: raise a warning, but do this only for products that aren't processed in MTO
            if not isMto:
                uom_record = False
                if uom:
                    uom_record = product_uom_obj.browse(cr,
                                                        uid,
                                                        uom,
                                                        context=context)
                    if product_obj.uom_id.category_id.id != uom_record.category_id.id:
                        uom_record = False
                if not uom_record:
                    uom_record = product_obj.uom_id
                compare_qty = float_compare(
                    product_obj.virtual_available,
                    qty,
                    precision_rounding=uom_record.rounding)
                if compare_qty == -1:
                    warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \
                        (qty, uom_record.name,
                         max(0,product_obj.virtual_available), uom_record.name,
                         max(0,product_obj.qty_available), uom_record.name)
                    warning_msgs += _(
                        "Not enough stock ! : ") + warn_msg + "\n\n"

        #update of warning messages
        if warning_msgs:
            warning = {
                'title': _('Configuration Error!'),
                'message': warning_msgs
            }
        res.update({'warning': warning})
        return res
Пример #29
0
 'tml_source':fields.selection([
     ('database','Database'),
     ('file','File'),
     ('parser','Parser'),
 ],'Template source', select=True),
 'parser_def': fields.text('Parser Definition'),
 'parser_loc':fields.char('Parser location', size=128, help="Path to the parser location. Beginning of the path must be start with the module name!\nLike this: {module name}/{path to the parser.py file}"),
 'parser_state':fields.selection([
     ('default',_('Default')),
     ('def',_('Definition')),
     ('loc',_('Location')),
 ],'State of Parser', select=True),
 'in_format': fields.selection(_get_in_mimetypes, 'Template Mime-type'),
 'out_format':fields.many2one('report.mimetypes', 'Output Mime-type'),
 'report_sxw_content': fields.function(_report_content,
     fnct_inv=_report_content_inv, method=True,
     type='binary', string='SXW content',),
 'active':fields.boolean('Active', help='Disables the report if unchecked.'),
 'report_wizard':fields.boolean('Report Wizard'),
 'copies': fields.integer('Number of Copies'),
 'fallback_false':fields.boolean('Disable Format Fallback'),
 'xml_id': fields.function(_get_xml_id, type='char', size=128, string="XML ID",
                           method=True, help="ID of the report defined in xml file"),
 'extras': fields.function(_get_extras, method=True, type='char', size='256', string='Extra options'),
 'deferred':fields.selection([
     ('off',_('Off')),
     ('adaptive',_('Adaptive')),
 ],'Deferred', help='Deferred (aka Batch) reporting, for reporting on large amount of data.'),
 'deferred_limit': fields.integer('Deferred Records Limit', help='Records limit at which you are invited to start the deferred process.'),
 'replace_report_id':fields.many2one('ir.actions.report.xml', 'Replace Report'),
 'wizard_id':fields.many2one('ir.actions.act_window', 'Wizard Action'),
Пример #30
0
class stock_picking(osv.osv):
    _inherit = "stock.picking"

    def _get_partner_to_invoice(self, cr, uid, picking, context=None):
        """ Inherit the original function of the 'stock' module
            We select the partner of the sales order as the partner of the customer invoice
        """
        saleorder_ids = self.pool['sale.order'].search(
            cr,
            uid, [('procurement_group_id', '=', picking.group_id.id)],
            context=context)
        saleorders = self.pool['sale.order'].browse(cr,
                                                    uid,
                                                    saleorder_ids,
                                                    context=context)
        if saleorders and saleorders[0]:
            saleorder = saleorders[0]
            return saleorder.partner_invoice_id.id
        return super(stock_picking,
                     self)._get_partner_to_invoice(cr,
                                                   uid,
                                                   picking,
                                                   context=context)

    def _get_sale_id(self, cr, uid, ids, name, args, context=None):
        sale_obj = self.pool.get("sale.order")
        res = {}
        for picking in self.browse(cr, uid, ids, context=context):
            res[picking.id] = False
            if picking.group_id:
                sale_ids = sale_obj.search(
                    cr,
                    uid, [('procurement_group_id', '=', picking.group_id.id)],
                    context=context)
                if sale_ids:
                    res[picking.id] = sale_ids[0]
        return res

    _columns = {
        'sale_id':
        fields.function(_get_sale_id,
                        type="many2one",
                        relation="sale.order",
                        string="Sale Order"),
    }

    def _create_invoice_from_picking(self,
                                     cr,
                                     uid,
                                     picking,
                                     vals,
                                     context=None):
        sale_obj = self.pool.get('sale.order')
        sale_line_obj = self.pool.get('sale.order.line')
        invoice_line_obj = self.pool.get('account.invoice.line')
        invoice_id = super(stock_picking,
                           self)._create_invoice_from_picking(cr,
                                                              uid,
                                                              picking,
                                                              vals,
                                                              context=context)
        if picking.group_id:
            sale_ids = sale_obj.search(
                cr,
                uid, [('procurement_group_id', '=', picking.group_id.id)],
                context=context)
            if sale_ids:
                sale_line_ids = sale_line_obj.search(
                    cr,
                    uid, [('order_id', 'in', sale_ids),
                          ('product_id.type', '=', 'service'),
                          ('invoiced', '=', False)],
                    context=context)
                if sale_line_ids:
                    created_lines = sale_line_obj.invoice_line_create(
                        cr, uid, sale_line_ids, context=context)
                    invoice_line_obj.write(cr,
                                           uid,
                                           created_lines,
                                           {'invoice_id': invoice_id},
                                           context=context)
        return invoice_id
Пример #31
0
class HrContract(orm.Model):

    _inherit = 'hr.contract'

    def _get_wage_ir(self, cr, uid, ids, fields, arg, context=None):
        res = {}
        obj_employee = self.pool.get('hr.employee')
        employee_ids = obj_employee.search(cr, uid,
                                           [('contract_ids.id', '=', ids[0])])
        employees = obj_employee.browse(cr, uid, employee_ids, context=context)
        for employee in employees:
            for contract in employee.contract_ids:
                if employee_ids:
                    INSS = (-482.93 if ((contract.wage) >= 4390.25) else
                            -((contract.wage) * 0.11) if
                            ((contract.wage) >= 2195.13) and
                            ((contract.wage) <= 4390.24) else -(
                                (contract.wage) * 0.09) if
                            ((contract.wage) >= 1317.08) and
                            ((contract.wage) <= 2195.12) else -(
                                (contract.wage) * 0.08))
                    lane = (contract.wage - employee.n_dependent + INSS)
                    first_lane = (-(0.275 * (lane) - 826.15))
                    l1 = Decimal(str(first_lane))
                    lane1 = l1.quantize(Decimal('1.10'), rounding=ROUND_DOWN)
                    option_one = float(lane1)
                    second_lane = (-(0.225 * (lane) - 602.96))
                    l2 = Decimal(str(second_lane))
                    lane2 = l2.quantize(Decimal('1.10'), rounding=ROUND_DOWN)
                    option_two = float(lane2)
                    third_lane = (-(0.150 * (lane) - 335.03))
                    l3 = Decimal(str(third_lane))
                    lane3 = l3.quantize(Decimal('1.10'), rounding=ROUND_DOWN)
                    option_three = float(lane3)
                    fourth_lane = (-(0.075 * (lane) - 134.08))
                    l4 = Decimal(str(fourth_lane))
                    lane4 = l4.quantize(Decimal('1.10'), rounding=ROUND_DOWN)
                    option_four = float(lane4)
                    if (lane >= 4463.81):
                        res[ids[0]] = option_one
                        return res
                    elif (lane <= 4463.80) and (lane >= 3572.44):
                        res[ids[0]] = option_two
                        return res
                    elif (lane <= 3572.43) and (lane >= 2679.30):
                        res[ids[0]] = option_three
                        return res
                    elif (lane <= 2679.29) and (lane >= 1787.78):
                        res[ids[0]] = option_four
                        return res
                    else:
                        return 0

    def _get_worked_days(self, cr, uid, ids, fields, arg, context=None):
        res = {}

        obj_worked_days = self.pool.get('hr.payslip.worked_days')
        worked_ids = obj_worked_days.search(cr, uid,
                                            [('contract_id', '=', ids[0])])
        if worked_ids:
            worked = obj_worked_days.browse(cr, uid, worked_ids[0])
            res[ids[0]] = worked.number_of_days
            return res
        else:
            res[ids[0]] = 0
            return res

    def _check_date(self, cr, uid, ids, fields, arg, context=None):
        res = {}

        comp_date_from = time.strftime('%Y-04-01')
        comp_date_to = time.strftime('%Y-02-28')
        obj_payslip = self.pool.get('hr.payslip')
        payslip_ids = obj_payslip.search(cr, uid,
                                         [('contract_id', '=', ids[0]),
                                          ('date_from', '<', comp_date_from),
                                          ('date_to', '>', comp_date_to)])
        if payslip_ids:
            res[ids[0]] = True
            return res
        else:
            res[ids[0]] = False
            return res

    def _check_voucher(self, cr, uid, ids, context=None):
        user = self.pool.get('res.users').browse(cr, uid, uid, context=context)

        for contract in self.browse(cr, uid, ids):
            if user.company_id.check_benefits:
                return True
            else:
                if contract.value_va == 0 or contract.value_vr == 0:
                    return True
                else:
                    return False
        return True

    _columns = {
        'value_va':
        fields.float('Valley Food', help='Daily Value Benefit'),
        'value_vr':
        fields.float('Meal valley', help='Daily Value Benefit'),
        'workeddays':
        fields.function(_get_worked_days, type='float'),
        'transportation_voucher':
        fields.float('Valley Transportation',
                     help='Percentage of monthly deduction'),
        'health_insurance_father':
        fields.float('Employee Health Plan',
                     help='Health Plan of the Employee'),
        'health_insurance_dependent':
        fields.float('Dependent Health Plan',
                     help='Health Plan for Spouse and Dependents'),
        'calc_date':
        fields.function(_check_date, type='boolean'),
        'aditional_benefits':
        fields.float('Aditional Benefits', help='Others employee benefits'),
        'ir_value':
        fields.function(_get_wage_ir,
                        type="float",
                        digits_compute=dp.get_precision('Payroll')),
    }

    _constraints = [[
        _check_voucher,
        u'The company settings do not allow the use of food voucher and simultaneous meal',
        ['value_va', 'value_vr']
    ]]

    _defaults = {'value_va': 0, 'value_vr': 0}
Пример #32
0
class account_invoice(osv.osv):
    def _amount_all(self, cr, uid, ids, name, args, context=None):
        '''
           Calculer les montants : untaxed,tax,total,discount,undiscount et mettre à jour le montant en toute lettre
           @return:timbre
           @return:amount_untaxed
           @return:amount_tax
           @return:amount_total
           @return:discount_total
           @return:undiscount_total
        '''
        res = {}
        var = 'Timbre'
        cr.execute('SELECT valeur FROM account_parametre WHERE designation=%s',
                   (var, ))
        timbre = cr.dictfetchone()['valeur']
        for invoice in self.browse(cr, uid, ids, context=context):
            res[invoice.id] = {
                'timbre': 0.0,
                'discount_total': 0.0,
                'amount_untaxed': 0.0,
                'undiscount_total': 0.0,
                'amount_tax': 0.0,
                'amount_total': 0.0,
            }

        for line in invoice.invoice_line:
            res[invoice.id]['discount_total'] += (
                line.quantity * line.price_unit) - line.price_subtotal
            res[invoice.id]['amount_untaxed'] += line.price_subtotal
            res[invoice.
                id]['undiscount_total'] += line.quantity * line.price_unit
        for line in invoice.tax_line:
            res[invoice.id]['amount_tax'] += line.amount
        res[invoice.id]['amount_total'] = res[invoice.id]['amount_tax'] + res[
            invoice.id]['amount_untaxed']
        if invoice.partner_id.timbre == True and invoice.type == 'out_invoice' or invoice.type == 'in_refund':
            res[invoice.id]['amount_total'] += timbre
            res[invoice.id]['timbre'] = timbre
        if (invoice.partner_id.supplier == True
                and invoice.type == 'in_invoice'):
            res[invoice.id]['amount_total'] += timbre
            res[invoice.id]['timbre'] = timbre

        amount_word = ""
        if res[invoice.id]['amount_total'] != 0.0:
            amount_word = Number_To_Word.Number_To_Word(
                res[invoice.id]['amount_total'], 'fr', 'Dinars', 'Millimes', 3)
            cr.execute('UPDATE account_invoice SET amount_word=%s WHERE id=%s',
                       (amount_word, invoice.id))

        return res

    def _get_supplier_id(self, cr, uid):
        supplier_id = self.pool.get('stock.location').search(
            cr, uid, [('name', '=', 'Suppliers')])[0]
        return supplier_id

    def button_reset_taxes(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        ctx = context.copy()
        ait_obj = self.pool.get('account.invoice.tax')
        for id in ids:
            cr.execute(
                "DELETE FROM account_invoice_tax WHERE invoice_id=%s AND manual is False",
                (id, ))
            partner = self.browse(cr, uid, id, context=ctx).partner_id
            if partner.lang:
                ctx.update({'lang': partner.lang})
            for taxe in ait_obj.compute(cr, uid, id, context=ctx).values():
                ait_obj.create(cr, uid, taxe)
        # Update the stored value (fields.function), so we write to trigger recompute
        self.pool.get('account.invoice').write(cr,
                                               uid,
                                               ids, {'invoice_line': []},
                                               context=ctx)

        return True

    def _amount_residual(self, cr, uid, ids, name, args, context=None):
        '''
           TODO: This fuction is not in use, check the amount_total and residual problem first
           Ajouter le timbre au montant total lors de l'inirialisation du montant residual
           @return:residual
        '''
        var = 'Timbre'
        cr.execute('SELECT valeur FROM account_parametre WHERE designation=%s',
                   (var, ))
        timbre = cr.dictfetchone()['valeur']
        result = {}
        for invoice in self.browse(cr, uid, ids, context=context):
            result[invoice.id] = 0.0
            if invoice.move_id:
                for m in invoice.move_id.line_id:
                    if ((m.account_id.type in ('receivable', 'payable'))
                            and (invoice.partner_id.timbre == True)):
                        result[
                            invoice.id] += m.amount_residual_currency + timbre
                    elif m.account_id.type in ('receivable', 'payable'):
                        result[
                            invoice.id] += m.amount_residual_currency + timbre
        return result

    def onchange_location_dest_id(self, cr, uid, ids, location_dest_id):
        return {
            'domain': {
                'cash_id': [('location_id', '=', location_dest_id),
                            ('state', '=', 'open')]
            }
        }

    def action_date_assign(self, cr, uid, ids, *args):
        ''' 
           Creer les mouvements de stocks pour les lignes de facture au comptant
           
        '''
        for inv in self.browse(cr, uid, ids):
            res = self.onchange_payment_term_date_invoice(
                cr, uid, inv.id, inv.payment_term.id, inv.date_invoice)
            if res and res['value']:
                self.write(cr, uid, [inv.id], res['value'])
            todo_moves = []

            for invoice_line in inv.invoice_line:
                if not invoice_line.product_id:
                    continue
                if inv.type == 'in_invoice' or inv.type == 'out_refund':  #
                    location_id = 8  #Partner locations/Suppliers
                    location_dest_id = 12  #Stock
                else:
                    location_id = 12  #Stock
                    location_dest_id = 9  #Partner locations/Customers
                if invoice_line.product_id.product_tmpl_id.type in ('consu'):
                    move = self.pool.get('stock.move').create(
                        cr, uid, {
                            'name': (invoice_line.name),
                            'product_id': invoice_line.product_id.id,
                            'location_id': location_id,
                            'location_dest_id': location_dest_id,
                            'partner_id': inv.partner_id.id,
                            'invoice_id': inv.id,
                            'product_uom_qty': invoice_line.quantity,
                            'product_uom': invoice_line.uos_id.id,
                            'product_uos': invoice_line.uos_id.id,
                            'state': 'done',
                            'price_unit': invoice_line.price_unit,
                            'picking_type_id': 1,
                        })
                if invoice_line.move_dest_id:
                    self.pool.get('stock.move').write(
                        cr,
                        uid,
                        [invoice_line.move_dest_id],
                    )
                todo_moves.append(move)
        return True

    @api.multi
    def invoice_validate(self):
        self._cr.execute(
            "SELECT amount_total FROM account_invoice WHERE id =%s ",
            (self.id, ))
        reste_a_payer = self._cr.dictfetchone()['amount_total']
        self._cr.execute(
            "UPDATE account_invoice SET reste_a_payer=%s WHERE id =%s ", (
                reste_a_payer,
                self.id,
            ))
        return self.write({'state': 'open'})

    def _get_invoice_tax(self, cr, uid, ids, context=None):
        result = {}
        for tax in self.pool.get('account.invoice.tax').browse(
                cr, uid, ids, context=context):
            result[tax.invoice_id.id] = True
        return result.keys()

    def _get_invoice_line(self, cr, uid, ids, context=None):
        result = {}
        for line in self.pool.get('account.invoice.line').browse(
                cr, uid, ids, context=context):
            result[line.invoice_id.id] = True
        return result.keys()

    def _get_invoice_from_line(self, cr, uid, ids, context=None):
        move = {}
        for line in self.pool.get('account.move.line').browse(cr,
                                                              uid,
                                                              ids,
                                                              context=context):
            if line.reconcile_partial_id:
                for line2 in line.reconcile_partial_id.line_partial_ids:
                    move[line2.move_id.id] = True
            if line.reconcile_id:
                for line2 in line.reconcile_id.line_id:
                    move[line2.move_id.id] = True
        invoice_ids = []
        if move:
            invoice_ids = self.pool.get('account.invoice').search(
                cr, uid, [('move_id', 'in', move.keys())], context=context)
        return invoice_ids

    def _get_invoice_from_reconcile(self, cr, uid, ids, context=None):
        move = {}
        for r in self.pool.get('account.move.reconcile').browse(
                cr, uid, ids, context=context):
            for line in r.line_partial_ids:
                move[line.move_id.id] = True
            for line in r.line_id:
                move[line.move_id.id] = True

        invoice_ids = []
        if move:
            invoice_ids = self.pool.get('account.invoice').search(
                cr, uid, [('move_id', 'in', move.keys())], context=context)
        return invoice_ids

    _name = "account.invoice"
    _order = "id desc"
    _inherit = 'account.invoice'

    _columns = {
        'amount_word':
        fields.char('Lettre', size=254, readonly=True),
        'timbre':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Timbre',
                        store=True,
                        method=True,
                        multi='all'),
        #'amount_word': fields.char('Lettre', size=254),
        'undiscount_total':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Total sans remise',
                        store=True,
                        method=True,
                        multi='all'),
        'discount_total':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Total Remise',
                        store=True,
                        method=True,
                        multi='all'),
        'amount_tax':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Total taxe',
                        store=True,
                        method=True,
                        multi='all'),
        'amount_untaxed':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Total NHT',
                        store=True,
                        method=True,
                        multi='all'),
        'amount_total':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Total',
                        store=True,
                        method=True,
                        multi='all'),
        'date_invoice':
        fields.date('Invoice Date',
                    required=True,
                    readonly=True,
                    states={'draft': [('readonly', False)]}),
        'residual':
        fields.function(_amount_residual,
                        method=True,
                        digits_compute=dp.get_precision('Account'),
                        string='Residual',
                        store={
                            'account.invoice':
                            (lambda self, cr, uid, ids, c={}: ids,
                             ['invoice_line', 'move_id', 'amount_total'], 50),
                            'account.invoice.tax':
                            (_get_invoice_tax, None, 50),
                            'account.invoice.line': (_get_invoice_line, [
                                'price_unit', 'invoice_line_tax_id',
                                'quantity', 'discount', 'invoice_id'
                            ], 50),
                            'account.move.line':
                            (_get_invoice_from_line, None, 50),
                            'account.move.reconcile':
                            (_get_invoice_from_reconcile, None, 50),
                        },
                        help="Remaining amount due."),
        'location_dest_id':
        fields.many2one(
            'stock.location',
            'Destination Location',
            states={'open': [('readonly', True)]},
            help="Location where the system will stock the finished products."
        ),
        'location_src_id':
        fields.many2one('stock.location',
                        'Source Location',
                        states={'open': [('readonly', True)]}),
        'number_invoicing_picking':
        fields.char('Code Facture', size=32),
        'montant_retenue':
        fields.float('Montant Retenue',
                     digits_compute=dp.get_precision('Account')),
        'reste_a_payer':
        fields.float('Reste à payer',
                     digits_compute=dp.get_precision('Account'),
                     readonly=True),
    }
Пример #33
0
                fp = None
                try:
                    fp = tools.file_open(report[name[:-8]], mode='rb')
                    data = report['report_type'] == 'aeroo' and base64.encodestring(fp.read()) or fp.read()
                except IOError, e:
                    if e.errno == 13:  # Permission denied on the template file
                        raise except_orm(_(e.strerror), e.filename)
                    else:
                        _logger.warning('IOERROR!', e)
                except Exception, e:
                    _logger.warning('Exception!', e)
                    fp = False
                    data = False
                finally:
                    if fp:
                        fp.close()
            res[report['id']] = data
        return res

    def _report_content_inv(self, cr, uid, rec_id, name, value, arg, context=None):
        if value:
            self.write(cr, uid, rec_id, {name + '_data': value}, context=context)
            
    _columns = {
        'report_sxw_content': old_fields.function(_report_content,
            fnct_inv=_report_content_inv, method=True,
            type='binary', string='SXW content'),
        }

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class base_price_change_order(osv.osv):

    def do_change_list_price(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        context.update({
            'active_ids': ids,
            })
        return {
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'okgj.list.price.change.base.price',
            'type': 'ir.actions.act_window',
            'target': 'new',
            'context': context,
        }

    def _get_warehouse_id(self, cr, uid, context=None):
        user_data = self.pool.get('res.users').browse(cr,uid, uid, context=context)
        warehouse_id = False
        for one_warehouse in user_data.warehouse_ids:
            warehouse_id = one_warehouse.id
            if warehouse_id:
                break
        return warehouse_id

    def _get_purchase_price(self, cr, uid, ids, fields_name, arg, context=None):
        if context is None:
            context = {}
        res = {}.fromkeys(ids, 0.0)
        purchase_line_obj = self.pool.get('purchase.order.line')
        for record in self.browse(cr, uid, ids, context=context):
            purchase_line_ids = purchase_line_obj.search(cr , uid, [
                ('product_id','=', record.product_id.id),
                ('state', 'in', ['confirmed', 'done'])
                ], order='create_date DESC', context=context, limit=1)
            if purchase_line_ids:
                res[record.id] = purchase_line_obj.browse(cr, uid, purchase_line_ids[0], context=context).price_unit
        return res
    
    def _get_approve_state(self, cr, uid, ids, fields_name, arg, context=None):
        if context is None:
            context = {}
        res = {}.fromkeys(ids, False)
        line_obj = self.pool.get('okgj.base.price.change.line')
        for record in self.browse(cr, uid, ids, context=context):
            if record.price_change_line_ids:
                res[record.id] = 'done'
                for one_line in record.price_change_line_ids:
                    if one_line.state != 'confirmed':
                        res[record.id] = 'wait_approve'
                        break
        return res

    def _approve_state_search(self, cr, uid, obj, name, args, domain=None, context=None):
        if context is None:
            context = {}
        res_ids = self.search(cr, uid, [], context=context)
        result = self._get_approve_state(cr, uid, res_ids, 'approve_state', '', context)
        if not args:
            return [('id', 'in', res_ids)]
        filter_state = args[0][2]
        approve_ids = [key for key in result if result[key] == filter_state]
        if not approve_ids:
            return [('id', '=', '0')]
        return [('id', 'in', approve_ids)]


    _inherit = 'okgj.base.price.change'
    _description = 'OKGJ Sale Price Change'
    _order = 'create_date DESC'
    _columns = {
        'create_uid':fields.many2one('res.users', u'创建人', readonly=True),
        'create_date':fields.datetime(u'创建日期', readonly=True),
        'write_uid':fields.many2one('res.users', u'修改人', readonly=True),
        'write_date':fields.datetime(u'修改日期', readonly=True),
        'warehouse_id':fields.many2one('stock.warehouse', u'物流中心', required=True, select=True, states={'draft':[('readonly', False)]}, readonly=True),
        'product_id':fields.many2one('product.product', u'商品', required=True, select=True, states={'draft':[('readonly', False)]}, readonly=True),
        'standard_price':fields.related('product_id', 'standard_price', string=u'成本价', type='float', readonly=True),
        'list_price':fields.related('product_id', 'list_price', string=u'会员价', type='float', readonly=True),
        'okkg_price':fields.related('product_id', 'okkg_price', string=u'快购价', type='float', readonly=True),
        'other_price':fields.related('product_id', 'other_price', string=u'市场价', type='float', readonly=True),
        'recent_purchase_price':fields.function(_get_purchase_price, type='float', string=u'最近采购价', readonly=True),
        ## 'standard_price':fields.float(u'成本价', digits_compute=dp.get_precision('Product Price'), states={'draft':[('readonly', False)],'reedit':[('readonly', False)]}, readonly=True),
        ## 'okkg_price':fields.float(u'快购价', digits_compute=dp.get_precision('Product Price'), states={'draft':[('readonly', False)],'reedit':[('readonly', False)]}, readonly=True),
        ## 'other_price':fields.float(u'市场价', digits_compute=dp.get_precision('Product Price'), states={'draft':[('readonly', False)],'reedit':[('readonly', False)]}, readonly=True),
        ## 'recent_purchase_price':fields.float(u'最近采购价', digits_compute=dp.get_precision('Product Price'), states={'draft':[('readonly', False)],'reedit':[('readonly', False)]}, readonly=True,),
        'price_change_line_ids':fields.one2many('okgj.base.price.change.line', 'base_price_change_id', u'价格更改明细', states={'draft':[('readonly', False)],'reedit':[('readonly', False)]}, readonly=True),
        'state':fields.selection([('draft', u'草稿'), ('reedit', u'再编辑'),('confirmed', u'已确认')], u'状态', readonly=True),
        'approve_state':fields.function(_get_approve_state, fnct_search=_approve_state_search, type='selection', string='审批状态', selection=[('wait_approve', u'待审批'), ('done', u'已审批')]),
        'name_template': fields.related('product_id', 'name_template', type='char', size=128, store=True, select=True, string="Template Name"),
        'default_code': fields.related('product_id', 'default_code', type='char', size=128, store=True, select=True, string="Product default code"),
    }

    _defaults = {
        'warehouse_id': _get_warehouse_id,
        'state': lambda *a:'draft',
    }

    def onchange_product_id(self, cr, uid, ids, product_id, warehouse_id, context=None):
        if context is None:
            context = {}
        res = {}
        if not (product_id and warehouse_id):
            return res
        product_obj = self.pool.get('product.product')
        purchase_line_obj = self.pool.get('purchase.order.line')
        change_line_obj = self.pool.get('okgj.base.price.change.line')
        product_data = product_obj.browse(cr, uid, product_id, context=context) 
        other_price = product_data.other_price
        okkg_price = product_data.okkg_price
        standard_price = product_data.standard_price
        list_price = product_data.list_price
        ## 多物流中心
        ## standard_price = product_obj.get_okgj_product_warehouse_cost(cr, uid, warehouse_id, product_id, context=context)[product_id]
        #最近采购价
        purchase_line_ids = purchase_line_obj.search(cr , uid, [
            ('product_id','=', product_id),
            ('state', 'in', ['confirmed', 'done'])
            ], order='create_date DESC', context=context, limit=1)
        recent_purchase_price = 0
        if purchase_line_ids:
            recent_purchase_price = purchase_line_obj.browse(cr, uid, purchase_line_ids[0], context=context).price_unit
        res = {'value':
               {'standard_price':standard_price,
                'list_price':list_price,
                'other_price': other_price,
                'okkg_price':okkg_price,
                'recent_purchase_price':recent_purchase_price,
                }}
        return res

    ## 上传
    def action_upload_all(self, cr, uid, ids, context=None):
        if context is None:
            context ={}
        if isinstance(ids, (int, long)):
            ids = [ids]
        line_obj = self.pool.get('okgj.base.price.change.line')
        for one_order in self.browse(cr, uid, ids, context=context):
            for one_line in one_order.price_change_line_ids:
                line_obj.action_upload_line(cr, uid, one_line.id, context=context)
        self.write(cr, uid, ids, {'state': 'confirmed'}, context=context)
        return True

    def action_reedit(self, cr, uid, ids, context=None):
        if context is None:
            context ={}
        if isinstance(ids, (int, long)):
            ids = [ids]
        line_obj = self.pool.get('okgj.base.price.change.line')
        for one_order in self.browse(cr, uid, ids, context=context):
            for one_line in one_order.price_change_line_ids:
                line_obj.action_reedit_line(cr, uid, one_line.id, context=context)
        self.write(cr, uid, ids, {'state': 'reedit'}, context=context)
        return True
                                                                          'ActionHelp': menu.action.help,
                                                                          'ModuleName': data_id.module,
                                                                          'XmlId': data_id.name},
                                                                         context=context))
                            res_mod_dic[
                                'doc_on_module'].append(self.title_help(cr, uid,
                                                                        mnames[
                                                                            data_id.module],
                                                                        data_id.module, context=context))
            except KeyError, e:
                self.__logger.warning(
                    'Data not found for reference %s[%s:%s.%s]', data_id.model,
                    data_id.res_id, data_id.model, data_id.name, exc_info=True)
            except Exception, e:
                self.__logger.warning('Unknown error while browsing %s[%s]',
                                      data_id.model, data_id.res_id,
                                      exc_info=True)
        # res_mod_dic['doc_on_module']=list(set(res_mod_dic['doc_on_module']))
        for key, value in res.iteritems():
            for k, v in res[key].iteritems():
                # TODO Make Generic or with regEx
                # Putting title on the begining.
                txt = "\n".join(sorted(v[:len(v) - 2]))
                res[key][k] = txt
        return res

    _columns = {
        'doc_on_module': fields.function(_get_docs, method=True,
                                         string='Documentation', type='text', multi="meta", store=False),
    }
class base_price_change_line(osv.osv):
    _name = 'okgj.base.price.change.line'
    _description = 'OKGJ Sale Price Change Line'
    _order = 'product_id desc, product_qty asc'

    def _price_state_search(self, cr, uid, obj, name, args, domain=None, context=None):
        if context is None:
            context = {}
        if not args:
            return []
        res_ids = self.search(cr, uid, [], context=context)
        price_state = args[0][2]
        price_data = self._get_price(cr, uid, res_ids, 'price_state', '', context=context)
        new_ids = [line_id for line_id in price_data if price_data[line_id].get('price_state', '') == price_state]
        if not new_ids:
            return [('id', '=', '0')]
        return [('id', 'in', new_ids)]
    
    def _get_price(self, cr, uid, ids, field_names, arg, context=None):
        if context is None:
            context = {}
        result = {}.fromkeys(ids, 0)
        product_obj = self.pool.get('product.product')
        for one_line in self.browse(cr, uid, ids, context=context):
            if one_line.product_id:
                min_price = one_line.product_id.okgj_cost_price * one_line.product_qty
                max_price = one_line.product_id.other_price * one_line.product_qty
                if one_line.product_price < min_price:
                    price_state = '1'
                elif one_line.product_price > max_price:
                    price_state = '2'
                else:
                    price_state = '3'
                result[one_line.id] = {
                    'min_price':min_price,
                    'max_price':max_price,
                    'price_state':price_state,
                    }
        return result

    def _get_purchase_price(self, cr, uid, ids, fields_name, arg, context=None):
        if context is None:
            context = {}
        res = {}.fromkeys(ids, 0.0)
        purchase_line_obj = self.pool.get('purchase.order.line')
        for record in self.browse(cr, uid, ids, context=context):
            purchase_line_ids = purchase_line_obj.search(cr , uid, [
                ('product_id','=', record.product_id.id),
                ('state', 'in', ['confirmed', 'done'])
                ], order='create_date DESC', context=context, limit=1)
            if purchase_line_ids:
                res[record.id] = purchase_line_obj.browse(cr, uid, purchase_line_ids[0], context=context).price_unit
        return res

    def _get_warehouse_id(self, cr, uid, context=None):
        """
        依用户ID返回用户的第一个物流中心
        """
        user_data = self.pool.get('res.users').browse(cr,uid, uid, context=context)
        warehouse_id = False
        for one_warehouse in user_data.warehouse_ids:
            warehouse_id = one_warehouse.id
            if warehouse_id:
                break
        return warehouse_id

    def verify_list_price(self, cr, uid, product_id, new_list_price, warehouse_id=None, context=None):
        """
        商品调OK价时验证是否可调
        """
        product_obj = self.pool.get('product.product') 
        cost_price = product_obj.read(cr, uid, product_id, ['standard_price'], context=context)['standard_price']
        ## 多物流中心上线
        ## cost_price = product_obj.get_okgj_product_warehouse_cost(cr, uid, warehouse_id, product_id, context=context)[product_id]
        if warehouse_id:
            line_ids = self.search(cr, uid, [
                ('product_id', '=', product_id),
                ('warehouse_id', '=', warehouse_id)
                ], order='product_price_unit ASC', context=context)
        else:
            line_ids = self.search(cr, uid, [
                ('product_id', '=', product_id),
                ], order='product_price_unit ASC', context=context)
        if line_ids:
            adjust_ratio = self.read(cr, uid, line_ids[0], ['adjust_ratio'], context=context)['adjust_ratio']
            lowest_new_unit_price = new_list_price * adjust_ratio
            if lowest_new_unit_price < cost_price:
                return False
        return True

    def update_list_price(self, cr, uid, product_id, new_list_price, warehouse_id=None, context=None):
        """
        商品调会员价时自动按比例更新组合价格并上传
        """
        product_obj = self.pool.get('product.product') 
        if warehouse_id:
            line_ids = self.search(cr, uid, [
                ('product_id', '=', product_id),
                ('warehouse_id', '=', warehouse_id)
                ], context=context)
        else:
            line_ids = self.search(cr, uid, [
                ('product_id', '=', product_id),
                ], context=context)
        for one_line in self.browse(cr, uid, line_ids, context=context):
            adjust_ratio = one_line.adjust_ratio
            qty = one_line.product_qty
            new_unit_price = adjust_ratio * new_list_price
            new_total_price = adjust_ratio * new_list_price * qty
            self.write(cr, uid, one_line.id, {
                'product_price_unit':new_unit_price,
                'product_price':new_total_price,
                }, context=context)
            if one_line.state in ['confirmed']:
                self.action_upload_line(cr, uid, one_line.id, context=context)
        return True

    _inherit = ['mail.thread', 'ir.needaction_mixin']
    _columns = {
        'create_uid':fields.many2one('res.users', u'创建人', readonly=True),
        'create_date':fields.datetime(u'创建日期', readonly=True),

        'base_price_change_id':fields.many2one('okgj.base.price.change', u'价格调整单号', ondelete='cascade', states={'draft':[('readonly', False)]}, readonly=True),
        'warehouse_id':fields.many2one('stock.warehouse', u'物流中心', select=True, states={'draft':[('readonly', False)]}, readonly=True),
        'product_id':fields.many2one('product.product', u'商品', select=True, required=True, states={'draft':[('readonly', False)]}, readonly=True),
        'name_template': fields.related('product_id', 'name_template', type='char', size=128, store=True, select=True, string="Template Name"),
        'default_code': fields.related('product_id', 'default_code', type='char', size=128, store=True, select=True, string="Product default code"),
        
        'list_price':fields.related('product_id', 'list_price', string=u'会员价', type='float', readonly=True),
        'okkg_price':fields.related('product_id', 'okkg_price', string=u'快购价', type='float', readonly=True),
        'other_price':fields.related('product_id', 'other_price', string=u'市场价', type='float', readonly=True),
        'recent_purchase_price':fields.function(_get_purchase_price, type='float', string=u'最近采购价', readonly=True),

        'product_qty':fields.integer(u'数量', required=True, track_visibility='onchange', states={'draft':[('readonly', False)]}, readonly=True),
        'adjust_ratio':fields.float(u'调价比率',digits_compute=dp.get_precision('Product Price'), states={'draft':[('readonly', False)],'reedit':[('readonly', False)]}, readonly=True, required=True),
        'product_price_unit':fields.float(u'单位价格', digits_compute=dp.get_precision('Product Price'), required=True, track_visibility='onchange', states={'draft':[('readonly', False)],'reedit':[('readonly', False)]}, readonly=True),
        'product_price':fields.float(u'总价', digits_compute=dp.get_precision('Product Price'), required=True, track_visibility='onchange', states={'draft':[('readonly', False)],'reedit':[('readonly', False)]}, readonly=True),
        'state': fields.selection([
            ('draft', u'草稿'),
            ('reedit', u'再编辑'),
            ('confirmed', u'确认'),
            ('need_reedit', u'驳回'),
            ], u'状态', required=True, readonly=True, track_visibility='onchange'),
        'min_price':fields.function(_get_price, type='float', string=u'最低价', digits_compute=dp.get_precision('Product Price'), multi='get_price'),
        'max_price':fields.function(_get_price, type='float', string=u'最高价', digits_compute=dp.get_precision('Product Price'), multi='get_price'),
        'price_state':fields.function(_get_price, type='selection', string=u'价格状态', fnct_search=_price_state_search,
                                             selection=[('1', u'低于成本价'),
                                                        ('2',u'高于市场价'),
                                                        ('3',u'正常')], multi='get_price'),
    }

    def _check_repeat(self, cr, uid, ids, context=None):
        """
        一个物流中心内同商品同数量的记录只能有一条
        """
        if context is None: context={}
        for line in self.browse(cr, uid, ids, context=context):
            has_exist = self.search(cr, uid, [
                ('warehouse_id', '=', line.warehouse_id.id),
                ('product_id', '=', line.product_id.id),
                ('product_qty', '=', line.product_qty),
                ], context=context)
            if len(has_exist) > 1:
                return False
        return True

    _constraints = [(_check_repeat, u'错误,该物流中心已存在同样数量的商品', [u'商品, 数量, 物流中心'])]

    _defaults = {
        'warehouse_id': _get_warehouse_id,
        'adjust_ratio': lambda self, cr, uid, context: 1,
        'state':lambda self, cr, uid, context:'draft',
    }

    def create(self, cr, uid, vals, context=None):
        base_price_change_id = vals.get('base_price_change_id', False)
        if base_price_change_id:
            price_change_obj = self.pool.get('okgj.base.price.change')
            price_change_data = price_change_obj.browse(cr, uid, base_price_change_id, context=context)
            vals.update({
                         'product_id':price_change_data.product_id.id,
                         'warehouse_id':price_change_data.warehouse_id.id,
                         })
        return super(base_price_change_line, self).create(cr, uid, vals, context=context)

    def onchange_product_qty_ratio(self, cr, uid, ids, product_id, product_qty, adjust_ratio, context=None):
        """
        通过变换商品或数量调整价格
        """
        if context is None:
            context = {}
        if not (product_id and product_qty):
            return {}
        adjust_ratio = adjust_ratio or 1
        list_price = self.pool.get('product.product').read(cr, uid, product_id, ['list_price'])['list_price']
        sale_price_unit = list_price * adjust_ratio or 0
        sale_price = list_price * product_qty * adjust_ratio or 0
        sale_price = sale_price_rounding(sale_price)
        res = {'value' : {
            'product_price_unit': sale_price_unit,
            'product_price': sale_price} }
        return res

    def onchange_product_price_unit(self, cr, uid, ids, product_id, product_qty, product_price_unit, context=None):
        """
        通过基础调整比例与总价
        """
        if context is None:
            context = {}
        if not (product_id and product_qty and product_price_unit):
            return {}
        list_price = self.pool.get('product.product').read(cr, uid, product_id, ['list_price'])['list_price']
        if list_price <= 0:
            return {}
        adjust_ratio = product_price_unit / list_price
        sale_price = product_price_unit * product_qty
        sale_price = sale_price_rounding(sale_price)
        res = {'value' : {
            'adjust_ratio': adjust_ratio,
            'product_price': sale_price} }
        return res

    def onchange_product_price(self, cr, uid, ids, product_id, product_qty, product_price, context=None):
        """
        通过总价调整比率与单价
        """
        if context is None:
            context = {}
        if not (product_id and product_qty and product_price):
            return {}
        list_price = self.pool.get('product.product').read(cr, uid, product_id, ['list_price'])['list_price']
        if list_price <= 0:
            return {}
        adjust_ratio = product_price / (product_qty * list_price)
        sale_price_unit = product_price / product_qty
        res = {'value' : {
            'adjust_ratio': adjust_ratio,
            'product_price_unit': sale_price_unit,
            } }
        return res

    def action_upload_line(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'state': 'confirmed'}, context=context)
        return True

    def action_reedit_line(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'state': 'reedit'}, context=context)
        return True

    def action_need_reedit_line(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'state': 'need_reedit'}, context=context)
        return True
Пример #37
0
		# direct access to the m2m table is the less convoluted way to achieve this (and is ok ACL-wise)
		cr.execute("""SELECT DISTINCT sol.id FROM sale_order_invoice_rel rel JOIN
												  sale_order_line sol ON (sol.order_id = rel.order_id)
									WHERE rel.invoice_id = ANY(%s)""", (list(ids),))
		return [i[0] for i in cr.fetchall()]

	_name = 'sale.order.line'
	_description = 'Sales Order Line'
	_columns = {
		'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
		'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}),
		'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."),
		'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
		'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
		'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean',
			store={
				'account.invoice': (_order_lines_from_invoice, ['state'], 10),
				'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10)}),
		'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}),
		'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
		 help="From stock: When needed, the product is taken from the stock or we wait for replenishment.\nOn order: When needed, the product is purchased or produced."),
		'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')),
		'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}),
		'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner',help="A partner to whom the particular product needs to be allotted."),
		'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product UoS'), required=True, readonly=True, states={'draft': [('readonly', False)]}),
		'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True, readonly=True, states={'draft': [('readonly', False)]}),
		'product_uos_qty': fields.float('Quantity (UoS)' ,digits_compute= dp.get_precision('Product UoS'), readonly=True, states={'draft': [('readonly', False)]}),
		'product_uos': fields.many2one('product.uom', 'Product UoS'),
		'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount'), readonly=True, states={'draft': [('readonly', False)]}),
		'th_weight': fields.float('Weight', readonly=True, states={'draft': [('readonly', False)]}),
		'state': fields.selection([('cancel', 'Cancelled'),('draft', 'Draft'),('confirmed', 'Confirmed'),('exception', 'Exception'),('done', 'Done')], 'Status', required=True, readonly=True,
				help='* The \'Draft\' status is set when the related sales order in draft status. \
Пример #38
0
            path = addons.get_module_resource(module.name, 'static', 'src', 'img', 'icon.png')
            if path:
                image_file = tools.file_open(path, 'rb')
                try:
                    res[module.id] = image_file.read().encode('base64')
                finally:
                    image_file.close()
        return res

    _columns = {
        'name': fields.char("Technical Name", size=128, readonly=True, required=True, select=True),
        'category_id': fields.many2one('ir.module.category', 'Category', readonly=True, select=True),
        'shortdesc': fields.char('Module Name', size=64, readonly=True, translate=True),
        'summary': fields.char('Summary', size=64, readonly=True, translate=True),
        'description': fields.text("Description", readonly=True, translate=True),
        'description_html': fields.function(_get_desc, string='Description HTML', type='html', method=True, readonly=True),
        'author': fields.char("Author", size=128, readonly=True),
        'maintainer': fields.char('Maintainer', size=128, readonly=True),
        'contributors': fields.text('Contributors', readonly=True),
        'website': fields.char("Website", size=256, readonly=True),

        # attention: Incorrect field names !!
        #   installed_version refer the latest version (the one on disk)
        #   latest_version refer the installed version (the one in database)
        #   published_version refer the version available on the repository
        'installed_version': fields.function(_get_latest_version,
            string='Latest Version', type='char'),
        'latest_version': fields.char('Installed Version', size=64, readonly=True),
        'published_version': fields.char('Published Version', size=64, readonly=True),

        'url': fields.char('URL', size=128, readonly=True),
Пример #39
0
    def get_counter(self,cr,uid,context=None):
        myids = self.search(cr, uid, [], context=context)
        for user in self.browse(cr,uid,myids,context=context):
            res = user.counter +1;
            isTrue =   self.write(cr, uid, user.id, {'counter': res}, context=context)
        return isTrue

    _name = "saas.user.info"
    _description = "saas.user.info"
    _columns = {
        'name': fields.char('Note', required=False,track_visibility='always', help=""),
        'user': fields.many2one('res.partner', 'partner', help=""),
        'host_name': fields.char('host_name',required=True, help=""),
        'host_type': fields.char('host_type',required=False , help=""),
        'server': fields.many2one('saas.server', 'server',required=True, help=""),
        'url_addres': fields.function(_get_full_url, type='char',string='url_addres'),
        'start_date': fields.datetime('start_date',required=False, help=""),
        'end_date': fields.function(_compute_exp_date, type = 'datetime',string='end_date'),
        'product_id':fields.many2one('product.product','product_id',required = False,help=''),
        'state': fields.function(_get_server_state, type='char', string='state'),
        'counter': fields.integer('counter',required=False , help=""),
    }
    _defaults = {
        'start_date': fields.datetime.now,
    }
    _sql_constraints = [
        ('host_name_uniq', 'unique (host_name)', 'host_name must be unique !'),
    ]

class saas_server(osv.osv):
    _inherit = ['mail.thread']
Пример #40
0
class account_move_line(osv.osv):
    def _is_payment_schedule(self,
                             cr,
                             uid,
                             ids,
                             fieldnames,
                             args,
                             context=None):
        result = dict.fromkeys(ids, 0)
        for record in self.browse(cr, uid, ids, context=context):
            # Display only record with following conditions
            if record.account_id.type in ('payable', 'receivable') \
                        and not record.reconcile_id \
                        and (record.date_maturity or not record.reconcile_partial_id):
                result[record.id] = True
            else:
                result[record.id] = False
        return result

    def _amount_residual2(self, cr, uid, ids, field_names, args, context=None):
        res = {}
        cr.execute("select id from account_account where type = 'liquidity'")
        cash_ids = map(lambda x: x[0], cr.fetchall())
        begin_balance = self.pool.get(
            'account.account').get_total_account_balance_ex(
                cr, uid, cash_ids, ['balance'])
        if context is None:
            context = {}
        cur_obj = self.pool.get('res.currency')
        for move_line in self.browse(cr, uid, ids, context=context):
            res[move_line.id] = {
                'amount_begin_balance': 0.0,
                'amount_residual2': 0.0,
                'amount_residual_currency2': 0.0,
                'amount_end_balance': 0.0,
            }

            if move_line.currency_id:
                move_line_total = move_line.amount_currency
            else:
                move_line_total = move_line.debit - move_line.credit
            line_total_in_company_currency = move_line.debit - move_line.credit
            context_unreconciled = context.copy()
            if move_line.reconcile_partial_id:
                for payment_line in move_line.reconcile_partial_id.line_partial_ids:
                    if payment_line.id == move_line.id:
                        continue
                    if payment_line.currency_id and move_line.currency_id and payment_line.currency_id.id == move_line.currency_id.id:
                        move_line_total += payment_line.amount_currency
                    else:
                        if move_line.currency_id:
                            context_unreconciled.update(
                                {'date': payment_line.date})
                            amount_in_foreign_currency = cur_obj.compute(
                                cr,
                                uid,
                                move_line.company_id.currency_id.id,
                                move_line.currency_id.id,
                                (payment_line.debit - payment_line.credit),
                                round=False,
                                context=context_unreconciled)
                            move_line_total += amount_in_foreign_currency
                        else:
                            move_line_total += (payment_line.debit -
                                                payment_line.credit)
                    line_total_in_company_currency += (payment_line.debit -
                                                       payment_line.credit)

            result = move_line_total
            res[move_line.id]['amount_begin_balance'] = begin_balance
            res[move_line.id][
                'amount_residual_currency2'] = move_line.currency_id and self.pool.get(
                    'res.currency').round(cr, uid, move_line.currency_id,
                                          result) or result
            res[move_line.
                id]['amount_residual2'] = line_total_in_company_currency
            ending_balance = begin_balance + line_total_in_company_currency
            res[move_line.id]['amount_end_balance'] = ending_balance
            begin_balance = ending_balance
        return res

    def _get_move_line(self, cr, uid, ids, context=None):
        """ return all account_move_line for the same partner_id of the updated account_voucher """
        move_line_ids = []
        for voucher in self.browse(cr, uid, ids, context=context):
            move_line_ids += self.pool.get('account.move.line').search(
                cr,
                uid, [('id', 'in',
                       [line.move_line_id.id for line in voucher.line_ids])],
                context=context)
        return move_line_ids

    _inherit = 'account.move.line'
    _order = 'date_maturity, id'
    _columns = {
        'is_payment_schedule':
        fields.function(_is_payment_schedule,
                        type='boolean',
                        string='Is Payment Schedule',
                        store={
                            'account.move.line':
                            (lambda self, cr, uid, ids, c={}: ids, None, 10),
                            'account.voucher': (_get_move_line, ['state'], 10)
                        }),
        'amount_begin_balance':
        fields.function(_amount_residual2,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='Begin Balance',
                        multi="residual"),
        'amount_residual_currency2':
        fields.function(_amount_residual2,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='Residual Amount Currency',
                        multi="residual"),
        'amount_residual2':
        fields.function(_amount_residual2,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='Residual Amount',
                        multi="residual"),
        'amount_end_balance':
        fields.function(_amount_residual2,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='End Balance',
                        multi="residual"),
    }

    def init(self, cr):
        # Only when first install, update the is_payment_schedule status.
        cr.execute("update account_move_line m1 \
                    set is_payment_schedule = \
                    (select case when type in ('payable','receivable') \
                    and reconcile_id is null \
                    and (date_maturity is not null or reconcile_partial_id is null) \
                    then true else false end \
                    from account_move_line m2 \
                    inner join account_account a on m2.account_id = a.id \
                    where m2.id = m1.id)\
                    where is_payment_schedule is null")
Пример #41
0
            ('cancel', 'Cancelled'),
            ('waiting_date', 'Waiting Schedule'),
            ('progress', 'Sales Order'),
            ('cc_auth', 'Draft Authorized'),
            ('manual', 'Sale to Invoice'),
            ('invoice_except', 'Invoice Exception'),
            ('shipping_except', 'Shipping Exception'),
            ('done', 'Done')
            ], 'Status', readonly=True, track_visibility='onchange',
            help="Gives the status of the quotation or sales order. \nThe exception status is automatically set when a cancel operation occurs in the processing of a document linked to the sales order. \nThe 'Waiting Schedule' status is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
        'cc_pre_auth':fields.boolean('Creditcard Pre-authorised'),
        'rel_account_voucher_id':fields.many2one('account.voucher', 'Related Payment'),
        'invoiced': fields.function(_invoiced, method=True, string='Paid',
        type='boolean', help="It indicates that an invoice has been paid.",
        store={
             'account.invoice'  : (_get_invoice, ['state'], 20),
             'sale.order'       : (lambda self, cr, uid, ids, c={}: ids, ['state'], 20),
             'account.voucher'  : (_get_voucher, ['state'], 20),
         }),
        'cc_ship_refund' : fields.boolean('Ship Refunded', readonly=True),
    }

    def copy(self, cr, uid, id, default=None, context=None):
        if default is None:
            default = {}
        if context is None:
            context = {}
        default = default.copy()
        default['rel_account_voucher_id'] = False
        default['cc_pre_auth'] = False
        default['cc_ship_refund'] = False
class NewReceiptLineWizard(orm.Model):
    ''' Wizard for New Receipt Wizard
    '''
    _name = 'new.receipt.line.wizard'
    _vat_rate = 1.22 # TODO keep in parameter field!
    _decimal = 2

    def onchange_move_prefilter_id(self, cr, uid, ids, pre_filter, context=None):
        ''' Force domain of product   
        '''
        res = {
            'domain': {'product_id': []},
            'value': {},
            }

        if pre_filter:
            res['domain']['product_id'].append(
                ('default_code', 'ilike', pre_filter))
            #res['value']['pre_filter'] = False
        return res

    def onchange_product_id(self, cr, uid, ids, product_id, qty, context=None):
        ''' Change default price from product form
        '''
        decimal = self._decimal
        
        res = {'value': {'price': 0.0}}
        if not product_id:
            return res
            
        product_pool = self.pool.get('product.product')    
        product_proxy = product_pool.browse(
            cr, uid, product_id, context=context)
        
        if not product_id:
            return res     
        
        # TODO change price?
        field_data = product_pool._get_metel_price_data(
            cr, uid, [product_id], context=context)
        #res['value']['price'] = product_proxy.lst_price
        price = round(field_data[product_id].get(
            'metel_sale', 0.0), decimal)
        cost = round(product_proxy.standard_price, decimal)
        price_vat = price * self._vat_rate
        try:
            res['value']['price'] = price # discounted!
            res['value']['cost'] = cost
            res['value']['price_vat'] = price_vat
            res['value']['subtotal'] = price * qty
        except:
            pass        
        return res

    def _get_subtotal_value(self, cr, uid, ids, fields, args, context=None):
        ''' Fields function for calculate 
        '''
        vat_rate = self._vat_rate
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            price_vat = line.price * vat_rate
            res[line.id] = {
                'price_vat': price_vat,
                'cost': line.product_id.standard_price,
                'subtotal': price_vat * line.qty,
                }
        return res
    
    _columns = {
        'wizard_id': fields.many2one('new.receipt.wizard', 'Wizard'),
        'pre_filter': fields.char('Pre filtro', size=50),        
        'product_id': fields.many2one('product.product', 'Product'),
        'uom_id': fields.related(
            'product_id', 'uom_id', 
            type='many2one', relation='product.uom', 
            string='UOM', readonly=True),
        'qty': fields.float('Q.', digits=(16, 2), required=True),
        #'standard_price': fields.float('Price', digits=(16, 4), required=True),
        'price': fields.float('Price', digits=(16, 4), required=True),
        'cost': fields.function(
            _get_subtotal_value, method=True, type='float', string='Cost',
            readonly=True, multi=True),                         
        'price_vat': fields.function(
            _get_subtotal_value, method=True, type='float', string='Price VAT',
            readonly=True, multi=True),                         
        'subtotal': fields.function(
            _get_subtotal_value, method=True, type='float', string='Subtotal',
            readonly=True, multi=True),
        }
Пример #43
0
 "invoice_lines": fields.many2many(
     "account.invoice.line",
     "rent_order_line_invoice_rel",
     "order_line_id",
     "invoice_id",
     "Invoice Lines",
     readonly=True,
 ),
 "price_unit": fields.float(
     "Unit Price",
     required=True,
     digits_compute=dp.get_precision("Product Price"),
     readonly=True,
     states={"draft": [("readonly", False)]},
 ),
 "price_subtotal": fields.function(_amount_line, string="Subtotal", digits_compute=dp.get_precision("Account")),
 "tax_id": fields.many2many(
     "account.tax",
     "rent_order_tax",
     "order_line_id",
     "tax_id",
     "Taxes",
     readonly=True,
     states={"draft": [("readonly", False)]},
 ),
 "product_uom_qty": fields.float(
     "Quantity",
     digits_compute=dp.get_precision("Product Unit of Measure"),
     required=True,
     readonly=True,
     states={"draft": [("readonly", False)]},
class NewReceiptWizard(orm.Model):
    ''' Wizard for New Receipt Wizard
    '''
    _name = 'new.receipt.wizard'

    # -------------------------------------------------------------------------
    # Wizard button event:
    # -------------------------------------------------------------------------
    def dummy_action(self, cr, uid, ids, context=None):
        ''' Refresh button
        '''
        return True

    def action_done(self, cr, uid, ids, context=None):
        ''' Event for button done
        '''
        if context is None: 
            context = {}
        
        name = self.pool.get('ir.sequence').get(cr, uid, 'new.receipt.wizard')
        self.write(cr, uid, ids, {
            'name': name,
            }, context=context)
        wiz_proxy = self.browse(cr, uid, ids, context=context)[0]
        force_date = wiz_proxy.force_date

        # ---------------------------------------------------------------------
        # Create new corresponding:
        # ---------------------------------------------------------------------
        # Pool used:
        company_pool = self.pool.get('res.company')
        picking_pool = self.pool.get('stock.picking')
        move_pool = self.pool.get('stock.move')        
        quant_pool = self.pool.get('stock.quant')                
        type_pool = self.pool.get('stock.picking.type')

        now = force_date or ('%s' % datetime.now())[:19]
        origin = 'CORRISPETTIVO %s' % now[:10]

        # ---------------------------------------------------------------------
        # Search or create daily picking:
        # ---------------------------------------------------------------------
        picking_ids = picking_pool.search(cr, uid, [
            ('corresponding', '=', True),
            ('origin', '=', origin),
            ], context=context)        
        if picking_ids:
            picking_id = picking_ids[0]
            picking = picking_pool.browse(
                cr, uid, picking_ids, context=context)[0]
            # Parameters:    
            picking_type = picking.picking_type_id
            location_id = picking_type.default_location_src_id.id
            location_dest_id = picking_type.default_location_dest_id.id                
            company_id = picking.company_id.id
        else:        
            company_id = company_pool.search(cr, uid, [], context=context)[0]
            company = company_pool.browse(cr, uid, company_id, context=context)

            # Type ID:
            type_ids = type_pool.search(cr, uid, [
                ('code', '=', 'outgoing'),
                ], context=context)
            if not type_ids:
                raise osv.except_osv(
                    _('Error'), 
                    _('Need setup of outgoing stock.picking.type!'),
                    )    
            picking_type = \
                type_pool.browse(cr, uid, type_ids, context=context)[0]
            location_id = picking_type.default_location_src_id.id
            location_dest_id = picking_type.default_location_dest_id.id
            
            picking_id = picking_pool.create(cr, uid, {
                'partner_id': company.partner_id.id,
                'company_id': company_id,
                'corresponding': True,
                #'account_id': account.id,
                'date': now,
                'min_date': now,
                'origin': origin,
                'picking_type_id': picking_type.id,
                'pick_move': 'out',
                'pick_state': 'delivered',
                #'state': 'delivered', # XXX not real!
                }, context=context)

        # ---------------------------------------------------------------------
        # Add stock movement line:
        # ---------------------------------------------------------------------
        receipt = wiz_proxy.name
        for line in wiz_proxy.line_ids:
            product = line.product_id
            price = line.price
            qty = line.qty
            
            # -----------------------------------------------------------------
            # Create stock movement:
            # -----------------------------------------------------------------
            move_id = move_pool.create(cr, uid, {
                'name': product.name,
                'product_uom': product.uom_id.id,
                'picking_id': picking_id,
                'picking_type_id': picking_type.id,
                'origin': 'Scontr: %s' % receipt,
                'product_id': product.id,
                'product_uom_qty': qty,
                'date': now,
                'location_id': location_id,
                'location_dest_id': location_dest_id,
                'state': 'done',
                'price_unit': price,
                }, context=context)

            # -----------------------------------------------------------------
            # Create quants:
            # -----------------------------------------------------------------
            quant_pool.create(cr, uid, {
                 'stock_move_id': move_id,
                 'qty': qty,
                 'cost': price,
                 'location_id': location_dest_id,
                 'company_id': company_id,
                 'product_id': product.id,
                 'in_date': now,
                }, context=context)
        
        return self.write(cr, uid, ids, {
            'state': 'done',
            }, context=context)

    def _get_total(self, cr, uid, ids, fields, args, context=None):
        ''' Fields function for calculate 
        '''
        vat = 1.22
        res = {}
        for receipt in self.browse(cr, uid, ids, context=context)[0]:
            res[receipt.id] = {'total': 0.0}
            for line in receipt.line_ids:
                subtotal = line.qty * line.price
                res[receipt.id]['total'] += subtotal
            res[receipt.id]['total_vat'] = res[receipt.id]['total'] * vat
        return res
        
    _columns = {
        'name': fields.char('# Receipt', size=25),
        'force_date': fields.date('Force date', 
            help='Force date instead take today!'),
        'total': fields.function(_get_total, method=True, 
            type='float', string='Total', multi=True),      
        'total_vat': fields.function(_get_total, method=True, 
            type='float', string='Total VAT', multi=True),
        'state': fields.selection([
            ('draft', 'Draft'),
            ('done', 'Done'),
            ], 'State', readonly=True),
        }

    _defaults = {
        # Default value for state:
        'name': lambda *x: 'Non confermato...',
        'state': lambda *x: 'draft',
        }
Пример #45
0
            result[rec.id] = rec.mode and rec.mode.type.name or ""
        return result

    def _name_get(self, cr, uid, ids, field_name, arg, context=None):
        result = {}
        for rec in self.browse(cr, uid, ids, context):
            result[rec.id] = rec.reference
        return result

    _columns = {
        'type': fields.selection([
            ('payable','Payable'),
            ('receivable','Receivable'),
            ],'Type', readonly=True, select=True),
        # invisible field to filter payment order lines by payment type
        'payment_type_name': fields.function(_payment_type_name_get, method=True, type="char", size=64, string="Payment type name"),
        # The field name is necessary to add attachement documents to payment orders
        'name': fields.function(_name_get, method=True, type="char", size=64, string="Name"),
        'create_account_moves': fields.selection([('bank-statement','Bank Statement'),('direct-payment','Direct Payment')],
                                                 'Create Account Moves',
                                                 required=True,
                                                 states={'done':[('readonly',True)]},
                                                 help='Indicates when account moves should be created for order payment lines. "Bank Statement" '\
                                                      'will wait until user introduces those payments in bank a bank statement. "Direct Payment" '\
                                                      'will mark all payment lines as payied once the order is done.'),
        'period_id': fields.many2one('account.period', 'Period', states={'done':[('readonly',True)]}),
    }
    _defaults = {
        'type': _get_type,
        'reference': _get_reference,
        'create_account_moves': lambda *a: 'bank-statement',
Пример #46
0
class account_invoice(osv.osv):

    _inherit = 'account.invoice'

    def render_description(self,
                           cr,
                           uid,
                           description,
                           invoice_id,
                           context=None):
        if not description:
            return u""
        if context is None:
            context = {}
        try:
            invoice = self.browse(cr, uid, invoice_id, context=context)
            user = self.pool.get('res.users').browse(cr, uid, uid, context)
            variables = {
                'object': invoice,
                'user': user,
                'ctx': context,
            }
            result = mako_template_env.from_string(description).render(
                variables)
            if result == u"False":
                result = u""
            return result
        except Exception:
            _logger.exception("failed to render description %r", description)
            return u""

    def _auto_invoice_amount_all(self, cr, uid, ids, name, args, context=None):
        res = {}
        tax_obj = self.pool.get('account.tax')
        for invoice in self.browse(cr, uid, ids, context=context):
            fp = invoice.fiscal_position
            res[invoice.id] = {
                'auto_invoice_amount_untaxed': 0.0,
                'auto_invoice_amount_tax': 0.0,
                'auto_invoice_amount_total': 0.0
            }
            for line in invoice.invoice_line:
                if fp and fp.active_reverse_charge and line.reverse_charge:
                    res[invoice.id][
                        'auto_invoice_amount_untaxed'] += line.price_subtotal
                    for t in tax_obj.compute_all(
                            cr, uid, line.invoice_line_tax_id,
                        (line.price_unit *
                         (1 - (line.discount or 0.0) / 100.0)), line.quantity,
                            line.product_id)['taxes']:
                        res[invoice.
                            id]['auto_invoice_amount_tax'] += t['amount']
                if (not fp) or (fp and not fp.active_reverse_charge):
                    res[invoice.id][
                        'auto_invoice_amount_untaxed'] += line.price_subtotal
                    for t in tax_obj.compute_all(
                            cr, uid, line.invoice_line_tax_id,
                        (line.price_unit *
                         (1 - (line.discount or 0.0) / 100.0)), line.quantity,
                            line.product_id)['taxes']:
                        res[invoice.
                            id]['auto_invoice_amount_tax'] += t['amount']
            res[invoice.id]['auto_invoice_amount_total'] = res[
                invoice.id]['auto_invoice_amount_tax'] + res[
                    invoice.id]['auto_invoice_amount_untaxed']
        return res

    _columns = {
        'transfer_entry_id':
        fields.many2one('account.move', 'Transfer Entry', ondelete="set null"),
        'auto_invoice_id':
        fields.many2one('account.invoice', 'Auto Invoice',
                        ondelete="set null"),
        'auto_invoice_amount_untaxed':
        fields.function(_auto_invoice_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Auto Invoice Subtotal',
                        store=False,
                        multi='auto_invoice_all'),
        'auto_invoice_amount_tax':
        fields.function(_auto_invoice_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Auto Invoice Tax',
                        store=False,
                        multi='auto_invoice_all'),
        'auto_invoice_amount_total':
        fields.function(_auto_invoice_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Auto Invoice Total',
                        store=False,
                        multi='auto_invoice_all'),
    }

    def voucher_from_invoice(self,
                             cr,
                             uid,
                             invoice_id,
                             amount,
                             journal_id,
                             voucher_type='payment',
                             context=None):
        context = context or {}
        voucher_obj = self.pool.get('account.voucher')
        invoice = self.browse(cr, uid, invoice_id, context)
        # ----- Voucher Header
        voucher_id = voucher_obj.create(
            cr, uid, {
                'name': invoice.name,
                'partner_id': invoice.partner_id.id,
                'amount': amount,
                'journal_id': journal_id,
                'account_id': invoice.account_id.id,
                'type': voucher_type,
            })
        move_line_ids = []
        # ----- Extract all the move lines from new invoice
        for l in invoice.move_id.line_id:
            if l.date_maturity:
                move_line_ids.append(l.id)
        context.update({
            'move_line_ids': move_line_ids,
            'invoice_id': invoice.id,
        })
        # ----- Voucher Lines
        voucher_lines = voucher_obj.recompute_voucher_lines(
            cr, uid, [voucher_id], invoice.partner_id.id,
            invoice.journal_id.id, amount, invoice.currency_id.id,
            voucher_type, invoice.date_invoice, context)
        voucher_lines_cr = []
        voucher_lines_dr = []
        for voucher_line in voucher_lines['value']['line_dr_ids']:
            voucher_lines_dr.append((0, 0, voucher_line))
        for voucher_line in voucher_lines['value']['line_cr_ids']:
            voucher_lines_cr.append((0, 0, voucher_line))
        voucher_obj.write(
            cr, uid, [
                voucher_id,
            ], {
                'line_dr_ids': voucher_lines_dr,
                'line_cr_ids': voucher_lines_cr,
                'pre_line': voucher_lines['value']['pre_line'],
                'writeoff_amount': voucher_lines['value']['writeoff_amount'],
            }, context)
        # ----- Post Voucher
        voucher_obj.button_proforma_voucher(cr, uid, [
            voucher_id,
        ], context)
        return voucher_id

    def _get_tax_relation(self, cr, uid, invoice_id, context=None):
        # ----- keep relation between tax and relative intra cee tax
        tax_relation = {}
        inv = self.browse(cr, uid, invoice_id)
        for line in inv.invoice_line:
            # ----- Check if tax has autoinvoice tax
            for tax in line.invoice_line_tax_id:
                tax_relation.update({tax.id: tax.auto_invoice_tax_id.id})
        return tax_relation

    def auto_invoice_vals(self,
                          cr,
                          uid,
                          invoice_id,
                          fiscal_position_id,
                          context=None):
        context = context or {}
        invoice = self.browse(cr, uid, invoice_id, context)
        fp_id = fiscal_position_id or invoice.fiscal_position.id
        fiscal_position = self.pool.get('account.fiscal.position').browse(
            cr, uid, fp_id, context)
        # ----- Get actual invoice copy
        copy_inv = self.copy_data(cr, uid, invoice_id, {}, context)
        if not copy_inv:
            return {}
        new_inv = copy_inv.copy()
        # ----- Change some data in new invoice
        new_inv.update({
            'type':
            invoice.type.replace('in_', 'out_'),
            'origin':
            invoice.number or '',
            'supplier_invoice_number':
            '',
            'internal_number':
            '',
            'number':
            '',
            'state':
            'draft',
            'move_id':
            False,
            'period_id':
            invoice.period_id and invoice.period_id.id or False,
            'account_id':
            invoice.partner_id.property_account_receivable.id,
            'journal_id':
            fiscal_position.journal_auto_invoice_id.id,
            'date_invoice':
            invoice.registration_date,
            'registration_date':
            invoice.registration_date,
        })
        new_line = []
        tax_relation = self._get_tax_relation(cr, uid, invoice_id, context)
        for line in new_inv['invoice_line']:
            vals = line[2].copy()
            # ----- Change account in new invoice line
            vals['account_id'] = fiscal_position.account_transient_id.id
            # ----- Change tax in new invoice line
            new_tax = []
            for tax in vals['invoice_line_tax_id']:
                new_tax.append((6, 0, [tax_relation[tax[2][0]]]))
            vals['invoice_line_tax_id'] = new_tax
            new_line.append((0, 0, vals))
        new_inv['invoice_line'] = new_line
        return new_inv

    def rc_auto_invoice_vals(self,
                             cr,
                             uid,
                             invoice_id,
                             fiscal_position_id,
                             context=None):
        # ----- Get complete invoice copy
        res = self.auto_invoice_vals(cr, uid, invoice_id, fiscal_position_id,
                                     context)
        # ----- Get partner from company for auto invoice
        company = self.pool.get('res.users').browse(cr, uid, uid,
                                                    context).company_id
        res['partner_id'] = company.auto_invoice_partner_id and \
            company.auto_invoice_partner_id.id \
            or res['partner_id']
        # ----- Delete line without reverse charge flag
        rc_lines = []
        for line in res['invoice_line']:
            if line[2]['reverse_charge']:
                rc_lines.append(line)
        res['invoice_line'] = rc_lines
        return res

    def extra_ue_auto_invoice_vals(self,
                                   cr,
                                   uid,
                                   invoice_id,
                                   fiscal_position_id,
                                   context=None):
        # ----- Get complete invoice copy
        res = self.auto_invoice_vals(cr, uid, invoice_id, fiscal_position_id,
                                     context)
        # ----- Get partner from company for auto invoice
        company = self.pool.get('res.users').browse(cr, uid, uid,
                                                    context).company_id
        res['partner_id'] = company.auto_invoice_partner_id and \
            company.auto_invoice_partner_id.id \
            or company.partner_id and company.partner_id.id
        # ----- Get right lines
        invoice = self.browse(cr, uid, invoice_id, context)
        fp_id = fiscal_position_id or invoice.fiscal_position.id
        fiscal_position = self.pool.get('account.fiscal.position').browse(
            cr, uid, fp_id, context)
        product_obj = self.pool.get('product.product')
        total = 0.0
        for line in res['invoice_line']:
            product = line[2]['product_id'] and product_obj.browse(
                cr, uid, line[2]['product_id']) or False
            if product and product.type == 'service' or not product:
                price_subtotal = line[2]['price_unit'] * (
                    1 - (line[2]['discount'] or 0.0) / 100.0)
                total += price_subtotal * line[2]['quantity']
        if not total:
            return False
        d = fiscal_position.extra_ue_line_detail
        res['invoice_line'] = [(0, 0, {
            'name':
            self.render_description(cr, uid, d, invoice_id, context),
            'price_unit':
            total,
            'quantity':
            1,
            'account_id':
            fiscal_position.account_transient_id.id,
            'invoice_line_tax_id':
            [(6, 0, [fiscal_position.extra_ue_service_tax_id.id])]
        })]
        return res

    def create_auto_invoice(self, cr, uid, ids, context=None):
        context = context or {}
        new_invoice_ids = []
        move_obj = self.pool.get('account.move')
        #~ wf_service = netsvc.LocalService("workflow")
        for inv in self.browse(cr, uid, ids, context):
            # ----- Apply Auto Invoice only on supplier invoice/refund
            if not (inv.type == 'in_invoice' or inv.type == 'in_refund'):
                continue
            fiscal_position = inv.fiscal_position
            # ----- Check if fiscal positon is active for intra CEE invoice
            if not fiscal_position:
                continue
            if not (fiscal_position.active_intra_cee
                    or fiscal_position.active_reverse_charge
                    or fiscal_position.active_extra_ue_service):
                continue
            # ----- keep relation between tax and relative intra cee tax
            for line in inv.invoice_line:
                # ----- Check if taxes exist on each line
                if not line.invoice_line_tax_id:
                    raise osv.except_osv(
                        _('Error'),
                        _('You must define a tax for each line \
                        in Intra CEE Invoice'))
                # ----- Check if tax has autoinvoice tax
                for tax in line.invoice_line_tax_id:
                    if not tax.auto_invoice_tax_id:
                        raise osv.except_osv(
                            _('Error'),
                            _('Set an Auto Invoice Tax for tax %s') %
                            (tax.name))
            # ----- Get actual invoice copy based on fiscal position flag
            if fiscal_position.active_intra_cee:
                new_inv = self.auto_invoice_vals(cr, uid, inv.id,
                                                 fiscal_position.id, context)
            elif fiscal_position.active_reverse_charge:
                new_inv = self.rc_auto_invoice_vals(cr, uid, inv.id,
                                                    fiscal_position.id,
                                                    context)
            elif fiscal_position.active_extra_ue_service:
                new_inv = self.extra_ue_auto_invoice_vals(
                    cr, uid, inv.id, fiscal_position.id, context)
            if not new_inv:
                continue
            # ----- Create Auto Invoice...Yeah!!!!!
            auto_invoice_id = self.create(cr, uid, new_inv, context)
            new_invoice_ids.append(auto_invoice_id)
            # ----- Recompute taxes in new invoice
            self.button_reset_taxes(cr, uid, [auto_invoice_id], context)
            # ----- Get new values from auto invoice
            new_invoice = self.browse(cr, uid, auto_invoice_id, context)
            # ----- Validate invoice
            new_invoice.signal_workflow('invoice_open')
            self.write(cr, uid, [inv.id], {'auto_invoice_id': auto_invoice_id},
                       context)

        return new_invoice_ids

    def action_number(self, cr, uid, ids, context=None):
        res = super(account_invoice, self).action_number(cr, uid, ids, context)
        self.create_auto_invoice(cr, uid, ids, context)
        return res

    def action_cancel(self, cr, uid, ids, context=None):
        invoices = self.browse(cr, uid, ids, context)
        account_move = self.pool.get('account.move')
        voucher_obj = self.pool.get('account.voucher')
        #~ wf_service = netsvc.LocalService("workflow")
        move_ids = []
        for inv in invoices:
            # ----- Delete Auto Invoice
            if inv.auto_invoice_id:
                # ----- Delete Payments for suppier invoice
                if len(inv.payment_ids) > 1:
                    raise osv.except_osv(
                        _('Error!'),
                        _('You cannot cancel an invoice which is partially \
                        paid. You need to unreconcile related payment entries \
                        first.'))
                payment_ids = []
                for payment in inv.payment_ids:
                    voucher_ids = voucher_obj.search(
                        cr, uid, [('move_id', '=', payment.move_id.id)])
                    if not voucher_ids:
                        continue
                    payment_ids = payment_ids + voucher_ids
                # ----- Delete Payments for auto invoice
                for payment in inv.auto_invoice_id.payment_ids:
                    voucher_ids = voucher_obj.search(
                        cr, uid, [('move_id', '=', payment.move_id.id)])
                    if not voucher_ids:
                        continue
                    payment_ids = payment_ids + voucher_ids
                if payment_ids:
                    voucher_obj.cancel_voucher(cr, uid, payment_ids, context)
                    voucher_obj.unlink(cr, uid, payment_ids, context)
                # ---- Delete Invoice
                inv.auto_invoice_id.signal_workflow('invoice_cancel')
                self.action_cancel_draft(cr, uid, [inv.auto_invoice_id.id])
                self.write(cr, uid, inv.auto_invoice_id.id,
                           {'internal_number': ''}, context)
                self.unlink(cr, uid, [inv.auto_invoice_id.id], context)
            # ----- Save account move ids
            if inv.transfer_entry_id:
                move_ids.append(inv.transfer_entry_id.id)
        # ----- Reopen and delete account move
        if move_ids:
            account_move.button_cancel(cr, uid, move_ids, context)
            account_move.unlink(cr, uid, move_ids, context)
        return super(account_invoice,
                     self).action_cancel(cr, uid, ids, context)

    @api.multi
    def finalize_invoice_move_lines(self, move_lines):
        super(account_invoice, self).finalize_invoice_move_lines(move_lines)
        # modify some data in move lines
        if (self.type == 'in_invoice' or self.type == 'in_refund'):
            fiscal_position = self.fiscal_position
            # ----- Check if fiscal positon is active for intra CEE invoice
            if not fiscal_position:
                return move_lines
            if not (fiscal_position.active_intra_cee
                    or fiscal_position.active_reverse_charge
                    or fiscal_position.active_extra_ue_service):
                return move_lines
            if fiscal_position.active_intra_cee:
                amount_vat = self.amount_tax

            if fiscal_position.active_reverse_charge:
                amount_vat = 0.0
                for tax in self.tax_line:
                    if not tax.base_code_id.rc:
                        continue
                    amount_vat += tax.amount
            if fiscal_position.active_extra_ue_service:
                amount_vat = self.amount_tax
            cli_account_id = self.partner_id.property_account_receivable.id
            new_line = {
                'name': '/',
                'debit': 0.0,
                'partner_id': self.partner_id.id,
                'account_id': cli_account_id
            }
            if self.type == 'in_invoice':
                new_line.update({'credit': amount_vat})
            if self.type == 'in_refund':
                new_line.update({'debit': amount_vat})
            reconcile = self.env['account.move.reconcile'].create(
                {'type': 'manual'})
            if reconcile:
                new_line.update({'reconcile_id': reconcile.id})
            number = 0
            for line in move_lines:
                if 'date_maturity' in line[2] \
                        and line[2]['date_maturity']:
                    number += 1
            for line in move_lines:
                if 'date_maturity' in line[2] \
                        and line[2]['date_maturity']:
                    if self.type == 'in_invoice':
                        line[2]['credit'] = line[2]['credit'] - (amount_vat /
                                                                 number)
                    if self.type == 'in_refund':
                        line[2]['debit'] = line[2]['debit'] - (amount_vat /
                                                               number)
            move_lines.append((0, 0, new_line))
        if (self.type == 'out_invoice' or self.type == 'out_refund'):
            if not self.origin:
                return move_lines
            ref_invoice = self.search([('internal_number', '=', self.origin)])
            if not ref_invoice:
                return move_lines
            if not ref_invoice.move_id:
                return move_lines
            reconcile_id = False
            for line in ref_invoice.move_id.line_id:
                if line.reconcile_id:
                    reconcile_id = line.reconcile_id.id
                    break

            fiscal_position = self.fiscal_position
            # ----- Check if fiscal positon is active for intra CEE invoice
            if not fiscal_position:
                return move_lines
            if not (fiscal_position.active_intra_cee
                    or fiscal_position.active_reverse_charge
                    or fiscal_position.active_extra_ue_service):
                return move_lines
            amount_vat = self.amount_tax
            cli_account_id = self.partner_id.property_account_receivable.id
            new_line = {
                'name': '/',
                'debit': 0.0,
                'partner_id': self.partner_id.id,
                'account_id': cli_account_id,
                'reconcile_id': reconcile_id,
            }
            if self.type == 'out_invoice':
                new_line.update({'debit': amount_vat})
            if self.type == 'out_refund':
                new_line.update({'credit': amount_vat})
            number = 0
            for line in move_lines:
                if 'date_maturity' in line[2] \
                        and line[2]['date_maturity']:
                    number += 1
            for line in move_lines:
                if 'date_maturity' in line[2] \
                        and line[2]['date_maturity']:
                    line[2][
                        'account_id'] = fiscal_position.account_transient_id.id
                    if self.type == 'out_invoice':
                        line[2]['debit'] = line[2]['debit'] - (amount_vat /
                                                               number)
                    if self.type == 'out_refund':
                        line[2]['credit'] = line[2]['credit'] - (amount_vat /
                                                                 number)
            move_lines.append((0, 0, new_line))
        return move_lines
Пример #47
0
                else:
                    price = 0.0
            res[carrier.id] = {"price": price, "available": available}
        return res

    _columns = {
        "name": fields.char("Delivery Method", required=True),
        "partner_id": fields.many2one(
            "res.partner", "Transport Company", required=True, help="The partner that is doing the delivery service."
        ),
        "product_id": fields.many2one("product.product", "Delivery Product", required=True),
        "grids_id": fields.one2many("delivery.grid", "carrier_id", "Delivery Grids"),
        "available": fields.function(
            get_price,
            string="Available",
            type="boolean",
            multi="price",
            help="Is the carrier method possible with the current order.",
        ),
        "price": fields.function(get_price, string="Price", multi="price"),
        "active": fields.boolean(
            "Active",
            help="If the active field is set to False, it will allow you to hide the delivery carrier without removing it.",
        ),
        "normal_price": fields.float(
            "Normal Price", help="Keep empty if the pricing depends on the advanced pricing per destination"
        ),
        "free_if_more_than": fields.boolean(
            "Free If Order Total Amount Is More Than",
            help="If the order is more expensive than a certain amount, the customer can benefit from a free shipping",
        ),
Пример #48
0
 'name':
 fields.char('Delivery Method', required=True),
 'partner_id':
 fields.many2one(
     'res.partner',
     'Transport Company',
     required=True,
     help="The partner that is doing the delivery service."),
 'product_id':
 fields.many2one('product.product', 'Delivery Product', required=True),
 'grids_id':
 fields.one2many('delivery.grid', 'carrier_id', 'Delivery Grids'),
 'available':
 fields.function(
     get_price,
     string='Available',
     type='boolean',
     multi='price',
     help="Is the carrier method possible with the current order."),
 'price':
 fields.function(get_price, string='Price', multi='price'),
 'active':
 fields.boolean(
     'Active',
     help=
     "If the active field is set to False, it will allow you to hide the delivery carrier without removing it."
 ),
 'normal_price':
 fields.float(
     'Normal Price',
     help=
     "Keep empty if the pricing depends on the advanced pricing per destination"
Пример #49
0
                cr, uid, line.taxes_id, line.price, line.qty, line.product_id, line.back_order_id.partner_id
            )
            cur = line.back_order_id.pricelist_id.currency_id
            res[line.id] = cur_obj.round(cr, uid, cur, taxes["total"])
        return res

    def _get_uom_id(self, cr, uid, context=None):
        try:
            proxy = self.pool.get("ir.model.data")
            result = proxy.get_object_reference(cr, uid, "product", "product_uom_unit")
            return result[1]
        except Exception, ex:
            return False

    _columns = {
        #        'location_destination_id': fields.many2one('stock.location', 'Stock Destination Location'),
        #        'location_id': fields.many2one('stock.location', 'Stock Source Location'),
        "product_id": fields.many2one("product.product", "Product"),
        "back_order_id": fields.many2one("back.to.back.order", "Back Order"),
        "qty": fields.float("Quantity"),
        "price": fields.float("Unit Price"),
        "subtotal": fields.function(_amount_line, string="Subtotal", digits_compute=dp.get_precision("Account")),
        "taxes_id": fields.many2many("account.tax", "purchase_order_taxe", "ord_id", "tax_id", "Taxes"),
        "product_uom": fields.many2one("product.uom", "Product Unit of Measure", required=True),
    }

    _defaults = {"product_uom": _get_uom_id}


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Пример #50
0
            path = addons.get_module_resource(module.name, 'static', 'src', 'img', 'icon.png')
            if path:
                image_file = tools.file_open(path, 'rb')
                try:
                    res[module.id] = image_file.read().encode('base64')
                finally:
                    image_file.close()
        return res

    _columns = {
        'name': fields.char("Technical Name", size=128, readonly=True, required=True, select=True),
        'category_id': fields.many2one('ir.module.category', 'Category', readonly=True, select=True),
        'shortdesc': fields.char('Module Name', size=64, readonly=True, translate=True),
        'summary': fields.char('Summary', size=64, readonly=True, translate=True),
        'description': fields.text("Description", readonly=True, translate=True),
        'description_html': fields.function(_get_desc, string='Description HTML', type='html', method=True, readonly=True),
        'author': fields.char("Author", size=128, readonly=True),
        'maintainer': fields.char('Maintainer', size=128, readonly=True),
        'contributors': fields.text('Contributors', readonly=True),
        'website': fields.char("Website", size=256, readonly=True),

        # attention: Incorrect field names !!
        #   installed_version refers the latest version (the one on disk)
        #   latest_version refers the installed version (the one in database)
        #   published_version refers the version available on the repository
        'installed_version': fields.function(_get_latest_version, string='Latest Version', type='char'),
        'latest_version': fields.char('Installed Version', size=64, readonly=True),
        'published_version': fields.char('Published Version', size=64, readonly=True),

        'url': fields.char('URL', size=128, readonly=True),
        'sequence': fields.integer('Sequence'),
Пример #51
0
    ('float', fields.float()),
    ('decimal', fields.float(digits=(16, 3))),
    ('string.bounded', fields.char('unknown', size=16)),
    ('string.required', fields.char('unknown', size=None, required=True)),
    ('string', fields.char('unknown', size=None)),
    ('date', fields.date()),
    ('datetime', fields.datetime()),
    ('text', fields.text()),
    ('selection', fields.selection([(1, "Foo"), (2, "Bar"), (3, "Qux"), (4, '')])),
    # here use size=-1 to store the values as integers instead of strings
    ('selection.function', fields.selection(selection_fn, size=-1)),
    # just relate to an integer
    ('many2one', fields.many2one('export.integer')),
    ('one2many', fields.one2many('export.one2many.child', 'parent_id')),
    ('many2many', fields.many2many('export.many2many.other')),
    ('function', fields.function(function_fn, fnct_inv=function_fn_write, type="integer")),
    # related: specialization of fields.function, should work the same way
    # TODO: reference
]

for name, field in models:
    class NewModel(orm.Model):
        _name = 'export.%s' % name
        _columns = {
            'const': fields.integer(),
            'value': field,
        }
        _defaults = {
            'const': 4,
        }
Пример #52
0
                file_data = image_file.read()
                self._logo_image = base64.encodestring(file_data)
                return self._logo_image
            finally:
                image_file.close()
        else:
            self._logo_image = base64.encodestring(im.read())
            return self._logo_image

    def _get_image_fn(self, cr, uid, ids, name, args, context=None):
        image = self._get_image(cr, uid, context)
        return dict.fromkeys(ids, image) # ok to use .fromkeys() as the image is same for all 

    _columns = {
        'printer_ids':fields.one2many('aeroo.printers.temp', 'install_id', 'Printers'),
        'config_logo': fields.function(_get_image_fn, string='Image', type='binary', method=True),
        'state':fields.selection([
            ('init','Init'),
            ('done','Done'),
            
        ],'State', select=True, readonly=True),
    }

    def default_get(self, cr, uid, fields, context=None):
        printers_obj = self.pool.get('aeroo.printers')
        data = super(aeroo_printer_installer, self).default_get(cr, uid, fields, context=context)
        conn = cups.Connection()
        printers = conn.getPrinters()
        installed_ids = printers_obj.search(cr, 1, ['|',('active','=',False),('active','=',True)], context=context)
        printers_installed = printers_obj.read(cr, uid, installed_ids, context=context)
        new_printers = list(set(printers.keys()).difference(set(map(lambda p: p['code'], printers_installed))))
Пример #53
0
                    price = 0.0
              else:
                  price = 0.0
            res[carrier.id] = {
                'price': price,
                'available': available
            }
        return res

    _columns = {
        'name': fields.char('Delivery Method', required=True, translate=True),
        'sequence': fields.integer('Sequence', help="Determine the display order"),
        'partner_id': fields.many2one('res.partner', 'Transport Company', required=True, help="The partner that is doing the delivery service."),
        'product_id': fields.many2one('product.product', 'Delivery Product', required=True),
        'grids_id': fields.one2many('delivery.grid', 'carrier_id', 'Delivery Grids'),
        'available' : fields.function(get_price, string='Available',type='boolean', multi='price',
            help="Is the carrier method possible with the current order."),
        'price' : fields.function(get_price, string='Price', multi='price'),
        'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the delivery carrier without removing it."),
        'normal_price': fields.float('Normal Price', help="Keep empty if the pricing depends on the advanced pricing per destination"),
        'free_if_more_than': fields.boolean('Free If Order Total Amount Is More Than', help="If the order is more expensive than a certain amount, the customer can benefit from a free shipping"),
        'amount': fields.float('Amount', help="Amount of the order to benefit from a free shipping, expressed in the company currency"),
        'use_detailed_pricelist': fields.boolean('Advanced Pricing per Destination', help="Check this box if you want to manage delivery prices that depends on the destination, the weight, the total of the order, etc."),
        'pricelist_ids': fields.one2many('delivery.grid', 'carrier_id', 'Advanced Pricing'),
    }

    _defaults = {
        'active': 1,
        'free_if_more_than': False,
        'sequence': 10,
    }
Пример #54
0
class product_template(osv.osv):
    _name = 'product.template'
    _inherit = 'product.template'
    
    def _product_available(self, cr, uid, ids, name, arg, context=None):
        prod_available = {}
        product_ids = self.browse(cr, uid, ids, context=context)
        var_ids = []
        for product in product_ids:
            var_ids += [p.id for p in product.product_variant_ids]
        variant_available= self.pool['product.product']._product_available(cr, uid, var_ids, context=context)

        for product in product_ids:
            qty_available = 0
            virtual_available = 0
            incoming_qty = 0
            outgoing_qty = 0
            for p in product.product_variant_ids:
                qty_available += variant_available[p.id]["qty_available"]
                virtual_available += variant_available[p.id]["virtual_available"]
                incoming_qty += variant_available[p.id]["incoming_qty"]
                outgoing_qty += variant_available[p.id]["outgoing_qty"]
            prod_available[product.id] = {
                "qty_available": qty_available,
                "virtual_available": virtual_available,
                "incoming_qty": incoming_qty,
                "outgoing_qty": outgoing_qty,
            }
        return prod_available

    def _search_product_quantity(self, cr, uid, obj, name, domain, context):
        prod = self.pool.get("product.product")
        product_variant_ids = prod.search(cr, uid, domain, context=context)
        return [('product_variant_ids', 'in', product_variant_ids)]

    def _product_available_text(self, cr, uid, ids, field_names=None, arg=False, context=None):
        res = {}
        for product in self.browse(cr, uid, ids, context=context):
            res[product.id] = str(product.qty_available) +  _(" On Hand")
        return res



    _columns = {
        'type': fields.selection([('product', 'Stockable Product'), ('consu', 'Consumable'), ('service', 'Service')], 'Product Type', required=True, help="Consumable: Will not imply stock management for this product. \nStockable product: Will imply stock management for this product."),
        'qty_available_text': fields.function(_product_available_text, type='char'),
        'property_stock_procurement': fields.property(
            type='many2one',
            relation='stock.location',
            string="Procurement Location",
            domain=[('usage','like','procurement')],
            help="This stock location will be used, instead of the default one, as the source location for stock moves generated by procurements."),
        'property_stock_production': fields.property(
            type='many2one',
            relation='stock.location',
            string="Production Location",
            domain=[('usage','like','production')],
            help="This stock location will be used, instead of the default one, as the source location for stock moves generated by manufacturing orders."),
        'property_stock_inventory': fields.property(
            type='many2one',
            relation='stock.location',
            string="Inventory Location",
            domain=[('usage','like','inventory')],
            help="This stock location will be used, instead of the default one, as the source location for stock moves generated when you do an inventory."),
        'sale_delay': fields.float('Customer Lead Time', help="The average delay in days between the confirmation of the customer order and the delivery of the finished products. It's the time you promise to your customers."),
        'loc_rack': fields.char('Rack', size=16),
        'loc_row': fields.char('Row', size=16),
        'loc_case': fields.char('Case', size=16),
        'track_incoming': fields.boolean('Track Incoming Lots', help="Forces to specify a Serial Number for all moves containing this product and coming from a Supplier Location"),
        'track_outgoing': fields.boolean('Track Outgoing Lots', help="Forces to specify a Serial Number for all moves containing this product and going to a Customer Location"),
        'track_all': fields.boolean('Full Lots Traceability', help="Forces to specify a Serial Number on each and every operation related to this product"),
        
        # sum of product variant qty
        # 'reception_count': fields.function(_product_available, multi='qty_available',
        #     fnct_search=_search_product_quantity, type='float', string='Quantity On Hand'),
        # 'delivery_count': fields.function(_product_available, multi='qty_available',
        #     fnct_search=_search_product_quantity, type='float', string='Quantity On Hand'),
        'qty_available': fields.function(_product_available, multi='qty_available', digits_compute=dp.get_precision('Product Unit of Measure'),
            fnct_search=_search_product_quantity, type='float', string='Quantity On Hand'),
        'virtual_available': fields.function(_product_available, multi='qty_available', digits_compute=dp.get_precision('Product Unit of Measure'),
            fnct_search=_search_product_quantity, type='float', string='Quantity Available'),
        'incoming_qty': fields.function(_product_available, multi='qty_available', digits_compute=dp.get_precision('Product Unit of Measure'),
            fnct_search=_search_product_quantity, type='float', string='Incoming'),
        'outgoing_qty': fields.function(_product_available, multi='qty_available', digits_compute=dp.get_precision('Product Unit of Measure'),
            fnct_search=_search_product_quantity, type='float', string='Outgoing'),
        
        'route_ids': fields.many2many('stock.location.route', 'stock_route_product', 'product_id', 'route_id', 'Routes', domain="[('product_selectable', '=', True)]",
                                    help="Depending on the modules installed, this will allow you to define the route of the product: whether it will be bought, manufactured, MTO/MTS,..."),
    }

    _defaults = {
        'sale_delay': 7,
    }

    def action_view_routes(self, cr, uid, ids, context=None):
        route_obj = self.pool.get("stock.location.route")
        act_obj = self.pool.get('ir.actions.act_window')
        mod_obj = self.pool.get('ir.model.data')
        product_route_ids = set()
        for product in self.browse(cr, uid, ids, context=context):
            product_route_ids |= set([r.id for r in product.route_ids])
            product_route_ids |= set([r.id for r in product.categ_id.total_route_ids])
        route_ids = route_obj.search(cr, uid, ['|', ('id', 'in', list(product_route_ids)), ('warehouse_selectable', '=', True)], context=context)
        result = mod_obj.xmlid_to_res_id(cr, uid, 'stock.action_routes_form', raise_if_not_found=True)
        result = act_obj.read(cr, uid, [result], context=context)[0]
        result['domain'] = "[('id','in',[" + ','.join(map(str, route_ids)) + "])]"
        return result


    def _get_products(self, cr, uid, ids, context=None):
        products = []
        for prodtmpl in self.browse(cr, uid, ids, context=None):
            products += [x.id for x in prodtmpl.product_variant_ids]
        return products
    
    def _get_act_window_dict(self, cr, uid, name, context=None):
        mod_obj = self.pool.get('ir.model.data')
        act_obj = self.pool.get('ir.actions.act_window')
        result = mod_obj.xmlid_to_res_id(cr, uid, name, raise_if_not_found=True)
        result = act_obj.read(cr, uid, [result], context=context)[0]
        return result
    
    def action_open_quants(self, cr, uid, ids, context=None):
        products = self._get_products(cr, uid, ids, context=context)
        result = self._get_act_window_dict(cr, uid, 'stock.product_open_quants', context=context)
        result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]"
        result['context'] = "{'search_default_locationgroup': 1, 'search_default_internal_loc': 1}"
        return result
    
    def action_view_orderpoints(self, cr, uid, ids, context=None):
        products = self._get_products(cr, uid, ids, context=context)
        result = self._get_act_window_dict(cr, uid, 'stock.product_open_orderpoint', context=context)
        if len(ids) == 1 and len(products) == 1:
            result['context'] = "{'default_product_id': " + str(products[0]) + ", 'search_default_product_id': " + str(products[0]) + "}"
        else:
            result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]"
            result['context'] = "{}"
        return result


    def action_view_stock_moves(self, cr, uid, ids, context=None):
        products = self._get_products(cr, uid, ids, context=context)
        result = self._get_act_window_dict(cr, uid, 'stock.act_product_stock_move_open', context=context)
        if len(ids) == 1 and len(products) == 1:
            ctx = "{'tree_view_ref':'stock.view_move_tree', \
                  'default_product_id': %s, 'search_default_product_id': %s}" \
                  % (products[0], products[0])
            result['context'] = ctx
        else:
            result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]"
            result['context'] = "{'tree_view_ref':'stock.view_move_tree'}"
        return result
Пример #55
0
class product_product(orm.Model):
    ''' Adds  a one2many field to the model to the Product which links 
    QC tests for certain triggers.'''
    _inherit = 'product.product'

    def _calc_trigger_ids(self, cr, uid, ids, fieldname, args, context=None):
        # TODO: Eliminar este método, que tampoco aporta mucho
        prod_trigger_obj = self.pool['product.qc.trigger.test']
        res = {}
        for product_id in ids:
            res[product_id] = []
            trigger_template_ids = prod_trigger_obj.search(
                cr, uid, [('product_id', '=', product_id)], context=context)
            for trigger_template in prod_trigger_obj.browse(
                    cr, uid, trigger_template_ids, context=context):
                if trigger_template.trigger_id.id not in res[product_id]:
                    res[product_id].append(trigger_template.trigger_id.id)
        return res

    def _search_trigger_ids(self, cr, uid, obj, name, args, context):
        trigger_template_proxy = self.pool['product.qc.trigger.test']
        res = []
        for unused, operator, condition in args:
            opposite = False
            if 'in' in operator:
                if operator == 'not in':
                    operator = 'in'
                    opposite = True
            else:
                if operator in ('!=', '<>'):
                    operator = '='
                    opposite = True
            template_trigger_ids = trigger_template_proxy.search(
                cr,
                uid, [
                    ('trigger_id', operator, condition),
                ],
                context=context)
            product_ids = []
            for template_trigger in trigger_template_proxy.browse(
                    cr, uid, template_trigger_ids, context):
                product_ids.append(template_trigger.product_id.id)
            operator = 'in'
            if opposite:
                operator = 'not in'
            res.append(('id', operator, product_ids))
        return res

    _columns = {
        'qc_test_trigger_ids':
        fields.one2many('product.qc.trigger.test',
                        'product_id',
                        'QC triggers > tests',
                        help="Defines when a product must to pass a quality "
                        "control test for certain operation.\n"),
        'qc_trigger_ids':
        fields.function(_calc_trigger_ids,
                        method=True,
                        type='many2many',
                        relation='qc.trigger',
                        string='QC triggers',
                        fnct_search=_search_trigger_ids),
    }

    def _default_qc_template_trigger_ids(self, cr, uid, context=None):
        # TODO: Esto no debería añadirse en los nuevos productos, si no cuando
        # se va a hacer el movimiento, mirar los tests que son de empresa
        user = self.pool['res.users'].browse(cr, uid, uid, context=context)
        res = []
        return res
        for company_trigger in user.company_id.qc_test_trigger_ids:
            res.append({
                'trigger_id': company_trigger.trigger_id.id,
                'template_id': company_trigger.template_id.id,
                'company_id': user.company_id.id,
            })
        return res

    _defaults = {
        'qc_test_trigger_ids': _default_qc_template_trigger_ids,
    }
Пример #56
0
class customer_reconcile(osv.osv):
    '''
    A customer reconcile is the document that associates already made payments with debts of the customer
    '''


    def _get_name(self, cr, uid, context=None):
        if context is None: context = {}
        return context.get('name', False)

    def _get_journal(self, cr, uid, context=None):
        if context is None: context = {}
        return context.get('journal_id', False)

    def _get_narration(self, cr, uid, context=None):
        if context is None: context = {}
        return context.get('narration', False)

    def _get_balance(self, cr, uid, ids, name, args, context=None):
        if not ids: return {}
        res = {}
        amount = 0.0
        for dr in self.browse (cr, uid, ids, context=context):
            u = []
            for uac in dr.uac_ids:
                u.append({'amount': uac.amount})
            db = []
            for debt in dr.debt_ids:
                db.append({'amount': debt.amount})

            res[dr.id] = self._compute_balance (cr, uid, u, db)
        return res

    def _compute_balance(self, cr, uid, uac_ids, debt_ids):
        currency_obj = self.pool.get('res.currency')

        balance = 0.0
        for uac in uac_ids:
            balance += uac['amount']
        for debt in debt_ids:
            balance -= debt['amount']

        return balance

    _name = 'numa_ar_base.customer_reconcile'
    _description = 'Deffered documents receipt'
    _order = "date desc, id desc"
    _columns = {
        'name':fields.char('Identification', size=256, readonly=True, states={'draft':[('readonly',False)]}),
        'date':fields.date('Date', readonly=True, select=True, states={'draft':[('readonly',False)]}, help="Efective operation date"),
        'journal_id':fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
        'account_id':fields.many2one('account.account', 'Account', required=True, readonly=True, states={'draft':[('readonly',False)]}),
        'uac_ids':fields.one2many('numa_ar_base.customer_reconcile_uac','cr_id','Non reconciled credits', readonly=True, states={'draft':[('readonly',False)]}),
        'debt_ids':fields.one2many('numa_ar_base.customer_reconcile_debt','cr_id','Applied debts', readonly=True, states={'draft':[('readonly',False)]}),
        'narration':fields.text('Notas', readonly=True, states={'draft':[('readonly',False)]}),
        'currency_id': fields.many2one('res.currency', string='Moneda', readonly=True, states={'draft':[('readonly',False)]}),
        'company_id': fields.related('journal_id','company_id', type='many2one', relation='res.company', string='Company', store=False, readonly=True),
        'state':fields.selection(
            [('draft','Draft'),
             ('posted','Posted'),
             ('cancel','Canceled')
            ], 'State', readonly=True, size=32,
            help=' * \'Draft\' state is used on new document entry. \
                        \n* \'Posted\' is used when the document is registered and account moves are generated \
                        \n* \'Cancel\' is used for canceled documents.'),
        'partner_id':fields.many2one('res.partner', 'Customer', change_default=1, readonly=True, states={'draft':[('readonly',False)]}),
        'balance': fields.function(_get_balance, method=True, string='Balance', type='float', readonly=True),
        'move_line_ids': fields.many2many('account.move.line', 'customer_reconcile_movements', 'cr_id', 'move_line_id', string='Reconcile', readonly=True, states={'draft':[('readonly',False)]}),
    }
    _defaults = {
        'name':_get_name,
        'journal_id':_get_journal,
        'narration':_get_narration,
        'state': 'draft',
        'name': '',
        'date': lambda *a: time.strftime('%Y-%m-%d'),
        'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'account.account', context=c),
    }

    def name_get(self, cr, uid, ids, context=None):
        if not ids:
            return []
        if context is None: context = {}
        customer_reconciles = self.browse (cr, uid, ids)
        return [(dr.id, "%s [%s]" % (dr.name, dr.company_id.name)) for dr in customer_reconciles]

    def onchange_line_ids(self, cr, uid, ids, uac_ids, debt_ids, context=None):
        uac_obj = self.pool.get('numa_ar_base.customer_reconcile_uac')
        debt_obj = self.pool.get('numa_ar_base.customer_reconcile_debt')

        u = resolve_o2m_operations(cr, uid, uac_obj, uac_ids, ['amount'], context=context)
        db = resolve_o2m_operations(cr, uid, debt_obj, debt_ids, ['amount'], context=context)
        
        return {'value': {'balance': self._compute_balance(cr, uid, u, db)}}

    def onchange_journal (self, cr, uid, ids, journal_id, partner_id, date, currency_id, context=None):
        default = {
            'value':{},
        }

        if not partner_id and not journal_id:
            return default

        cash_obj = self.pool.get('numa_ar_base.customer_reconcile_cash')
        journal_obj = self.pool.get('account.journal')
        period_obj = self.pool.get('account.period')

        journal = journal_obj.browse (cr, uid, journal_id, context=context)
        
        default['value']['currency_id'] = journal.currency.id or journal.company_id.currency_id.id
        default['value']['account_id'] = journal.default_debit_account_id.id
        default['value']['company_id'] = journal.company_id.id
            
        if partner_id:
            change_set = self.onchange_partner_id(cr, uid, ids, partner_id, journal_id, date, default['value']['currency_id'], context=context)
            default['value'].update(change_set['value'])

        return default

    def onchange_partner_id(self, cr, uid, ids, partner_id, journal_id, date, currency_id, context=None):
        if context is None:
            context = {}

        if not partner_id or not journal_id:
            return {}

        currency_pool = self.pool.get('res.currency')
        move_line_pool = self.pool.get('account.move.line')
        partner_pool = self.pool.get('res.partner')
        journal_pool = self.pool.get('account.journal')

        journal = journal_pool.browse (cr, uid, journal_id)
        company_id = journal.company_id.id

        company_currency_id = (journal.currency and journal.currency.id) or journal.company_id.currency_id.id

        total_debit = 0.0
        total_credit = 0.0

        default = {'value': {'debt_ids': [], 'uac_ids': []}}

        domain = [('state','=','valid'), ('account_id.type', '=', 'receivable'), ('reconcile_id', '=', False), 
                  ('partner_id', '=', partner_id), ('company_id', '=', company_id)]
        ids = move_line_pool.search(cr, uid, domain, context=context)    
        moves = move_line_pool.browse(cr, uid, ids, context=context)

        credits = []
        debits = []

        for line in moves:
            original_amount = line.debit or line.credit or 0.0
            amount_unreconciled = currency_pool.compute(cr, uid, line.currency_id.id or company_currency_id, currency_id, abs(line.amount_residual))
            amount_original = currency_pool.compute(cr, uid, line.currency_id.id or company_currency_id, currency_id, original_amount)
            rs = {
                'name':line.move_id.name,
                'move_line_id':line.id,
                'account_id':line.account_id.id,
                'analytic_account_id':line.analytic_account_id.id,
                'amount_original': amount_original,
                'date_original':line.date,
                'date_due':line.date_maturity,
                'amount_unreconciled': amount_unreconciled,
                'company_id': journal.company_id.id,
            }

            if line.credit:
                if not (line.reconcile_id or line.reconcile_partial_id):
                    rs['amount'] = amount_unreconciled
                    total_credit += amount_unreconciled
                    credits.append(rs)
            elif line.debit:
                rs['amount'] = 0
                debits.append(rs)

        credits.sort(key=lambda line: line['date_original'])
        debits.sort(key=lambda line: line['date_original'])

        #Apply credit in order to debts
        for debt in debits:
            applied_amount = min(debt['amount_unreconciled'], total_credit)
            debt['amount'] = applied_amount
            total_credit -= applied_amount

        default['value']['uac_ids'] = credits
        default['value']['debt_ids'] = debits

        return default

    def onchange_date(self, cr, uid, ids, date, journal_id, context=None):
        """
        @param date: latest value from user input for field date
        @param args: other arguments
        @param context: context arguments, like lang, time zone
        @return: Returns a dict which contains new values, and context
        """
        if not date:
            return False

        if not context: context = {}

        period_pool = self.pool.get('account.period')
        journal_pool = self.pool.get('account.journal')

        res = {'value':{}}

        if journal_id:
            journal = journal_pool.browse (cr, uid, journal_id)
            pids = period_pool.search(cr, uid, [('date_start', '<=', date), ('date_stop', '>=', date), ('company_id', '=', journal.company_id.id)])
        else:
            pids = period_pool.search(cr, uid, [('date_start', '<=', date), ('date_stop', '>=', date)])
        if not pids:
            raise osv.except_osv(_('Error!'), _('No period for receipt date!'))

        return res

    def unlink(self, cr, uid, ids, context=None):
        for t in self.read(cr, uid, ids, ['state'], context=context):
            if t['state'] not in ('draft', 'canceled'):
                raise osv.except_osv(_('Error!'), _('Posted documents could not be cancelled!'))
        return super(customer_reconcile, self).unlink(cr, uid, ids, context=context)

    def action_post(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        move_obj = self.pool.get('account.move')
        move_line_obj = self.pool.get('account.move.line')
        currency_obj = self.pool.get('res.currency')
        seq_obj = self.pool.get('ir.sequence')
        account_obj = self.pool.get('account.account')
        company_obj = self.pool.get('res.company')
        partner_obj = self.pool.get('res.partner')
        property_obj = self.pool.get('ir.property')
        period_obj = self.pool.get('account.period')

        for receipt in self.browse(cr, uid, ids, context=context):
            context_multi_currency = context.copy()
            context_multi_currency.update({'date': receipt.date})

            if receipt.journal_id and receipt.journal_id.sequence_id:
                name = seq_obj.get_id(cr, uid, receipt.journal_id.sequence_id.id, context={'company_id': receipt.journal_id.company_id.id})
            else:
                raise osv.except_osv(_('Error !'), _('Please define a Journal with sequence!'))

            pids = period_obj.search(cr, uid, [('date_start', '<=', receipt.date), ('date_stop', '>=', receipt.date), ('company_id', '=', receipt.journal_id.company_id.id)])
            if pids:
                period_id = pids[0]
            else:
                raise osv.except_osv(_('Error !'), _('No valid period for the entered date!'))

            ref = name.replace('/','')

            self.write (cr, uid, [receipt.id], {'name': name})

            company_currency = receipt.journal_id.company_id.currency_id.id
            current_currency = receipt.currency_id.id

            debit = 0.0
            #Compute the total amount to be payed
            total_credit = 0.0

            for uac in receipt.uac_ids:
                total_credit += uac.amount

            if total_credit == 0:
                    raise osv.except_osv(_('Not complete document!'),
                        _('No credit was entered!'))

            applicable_debts = []
            for line in receipt.debt_ids:
                if line.amount:
                    applicable_debts.append(line)

            debt_index = 0
            if len(applicable_debts):
                debt = applicable_debts[debt_index]
                left_to_apply = min (debt.amount_unreconciled, debt.amount)

            reconcile_lines = []
            reconcile_new_lines = []

            #Process unassigned credit entries

            #pdb.set_trace()

            for uac in receipt.uac_ids:

                amount_to_apply = uac.amount

                if amount_to_apply and debt_index < len(applicable_debts):
                    #Apply this amount to debts not yet covered

                    while debt_index < len(applicable_debts) and amount_to_apply > 0:
                        #Taking the amount to apply, try to cover as many docs as possible
                        #we check if the voucher line is fully paid or not and create a move line to balance the payment and initial invoice if needed

                        to_apply = min (amount_to_apply, left_to_apply)

                        if to_apply:
                            old = uac.move_line_id
                            if (uac.amount_original-uac.amount+amount_to_apply) > to_apply:
                                new_line_data = {
                                    'move_id': old.move_id.id,
                                    'account_id': old.account_id.id,
                                    'partner_id': old.partner_id.id,
                                    'name': old.name,
                                    'ref': old.ref,
                                    'date_maturity': old.date_maturity,
                                    'credit': to_apply,
                                    'debit': 0.0,
                                    'state': 'valid',
                                }

                                new_line_id = move_line_obj.create (cr, uid, new_line_data, check=False)

                                reconcile_new_lines.append(new_line_id)

                                if debt.move_line_id.id:
                                    rec_ids = [new_line_id, debt.move_line_id.id]
                                    reconcile_lines.append(rec_ids)
                            else:
                                move_line_obj.write(cr, uid, [old.id], {
                                                    'credit': to_apply, 
                                                    'debit': 0.0}, check=False, update_check=False)
                                reconcile_new_lines.append(old.id)

                                if debt.move_line_id.id:
                                    rec_ids = [old.id, debt.move_line_id.id]
                                    reconcile_lines.append(rec_ids)

                            amount_to_apply -= to_apply
                            left_to_apply -= to_apply


                        if not left_to_apply or not to_apply:
                            debt_index += 1
                            if debt_index < len(applicable_debts):
                                debt = applicable_debts[debt_index]
                                left_to_apply = min (debt.amount_unreconciled, debt.amount)

                    if (uac.amount_original-uac.amount+amount_to_apply) > 0:
                        move_line_obj.write(cr, uid, [uac.move_line_id.id], {
                                            'credit': uac.amount_original-uac.amount+amount_to_apply, 
                                            'debit': 0.0}, check=False, update_check=False)

            #Trigger reconcile on all affected debts

            self.write (cr, uid, [receipt.id], {'state': 'posted', 'move_line_ids': [(6, 0, reconcile_new_lines)]})

            for rec_ids in reconcile_lines:
                if len(rec_ids) >= 2:
                    move_line_obj.reconcile_partial(cr, uid, rec_ids)

        return True

    def copy(self, cr, uid, id, default={}, context=None):
        default.update({
            'state': 'draft',
            'number': False,
            'move_id': False,
            'qm_ids': False,
            #'doc_ids': False,
            'debt_ids': False,
            'reference': False
        })
        if 'date' not in default:
            default['date'] = time.strftime('%Y-%m-%d')
        return super(customer_reconcile, self).copy(cr, uid, id, default, context)
Пример #57
0
        'auto_currency_up': fields.boolean('Automatical update of the currency this company'),
        'services_to_use' : fields.one2many(
                                            'currency.rate.update.service',
                                            'company_id',
                                            'Currency update services'
                                            ),
        ###predifine cron frequence
        'interval_type': fields.selection(
                                                [
                                                    ('days','Day(s)'),
                                                    ('weeks', 'Week(s)'),
                                                    ('months', 'Month(s)')
                                                ],
                                                'Currency update frequence',
                                                help="""changing this value will
                                                 also affect other compagnies"""
                                            ),
        ###function field that allows to know the
        ###mutli company currency implementation
        'multi_company_currency_enable' : fields.function(
                                            _multi_curr_enable,
                                            method=True,
                                            type='boolean',
                                            string="Multi company currency",
                                            help='if this case is not check you can'+\
                                            ' not set currency is active on two company'
                                        ),
    }


Пример #58
0
class account_bank_statement(orm.Model):
    _inherit = 'account.bank.statement'

    def _get_statement_years(self, cr, uid, fields, context=None):
        result = []
        first_statement_id = self.search(cr,
                                         uid, [('date', '!=', False)],
                                         order='date asc',
                                         limit=1,
                                         context=context)
        if first_statement_id:
            first_statement = self.browse(cr, uid, first_statement_id[0],
                                          context)
            first_year = datetime.datetime.strptime(first_statement.date,
                                                    '%Y-%m-%d').year
        else:
            first_year = datetime.date.today().year

        for year in range(int(first_year),
                          int(datetime.date.today().year) + 1):
            result.append((str(year), str(year)))

        return result

    def _get_statement_year(self, cr, uid, ids, field_name, arg, context):

        result = {}
        for statement in self.browse(cr, uid, ids, context):
            if statement.date_invoice:
                result[statement.id] = datetime.datetime.strptime(
                    statement.date, '%Y-%m-%d').year
            else:
                result[statement.id] = False

        return result

    _columns = {
        'year':
        fields.function(_get_statement_year,
                        'Year',
                        type='selection',
                        selection=_get_statement_years,
                        method=True,
                        help="Select year"),
        'date_from':
        fields.function(lambda *a, **k: {},
                        method=True,
                        type='date',
                        string="Date from"),
        'date_to':
        fields.function(lambda *a, **k: {},
                        method=True,
                        type='date',
                        string="Date to"),
        'partner_id':
        fields.related('line_ids',
                       'partner_id',
                       type='many2one',
                       relation='res.partner',
                       string='Partner'),
    }

    def search(self,
               cr,
               uid,
               args,
               offset=0,
               limit=0,
               order=None,
               context=None,
               count=False):
        new_args = []
        for arg in args:
            if arg[0] == 'year':
                new_args.append(
                    ('date', '>=', '{year}-01-01'.format(year=arg[2])))
                new_args.append(
                    ('date', '<=', '{year}-12-31'.format(year=arg[2])))
            else:
                new_args.append(arg)

        return super(account_bank_statement, self).search(cr,
                                                          uid,
                                                          new_args,
                                                          offset=offset,
                                                          limit=limit,
                                                          order=order,
                                                          context=context,
                                                          count=count)
Пример #59
0
                )
            else:
                return False

        return self.write(cr, uid, id, {"file_db_store": value}, context=context)

    _columns = {
        "name": fields.char("Image Title", size=64),
        "filename": fields.char("Filename", size=64),
        "extension": fields.char("file extension", oldname="extention"),
        "link": fields.boolean(
            "Link?", help="Images can be linked from files on " "your file system or remote (Preferred)"
        ),
        "file_db_store": fields.binary("Image stored in database"),
        "file": fields.function(
            _get_image, fnct_inv=_set_image, type="binary", string="File", filters="*.png,*.jpg,*.gif"
        ),
        "url": fields.char("File Location"),
        "url_big": fields.char("File Location Image Size Big"),
        "url_medium": fields.char("File Location Image Size Medium"),
        "url_small": fields.char("File Location Image Size Small"),
        "comments": fields.text("Comments"),
        "product_id": fields.many2one("product.product", "Product"),
    }

    _defaults = {"link": True}

    _sql_constraints = [
        (
            "uniq_name_product_id",
            "UNIQUE(product_id, name)",
Пример #60
0
class product_product(osv.osv):
    _inherit = "product.product"
        
    def _stock_move_count(self, cr, uid, ids, field_name, arg, context=None):
        res = dict([(id, {'reception_count': 0, 'delivery_count': 0}) for id in ids])
        move_pool=self.pool.get('stock.move')
        moves = move_pool.read_group(cr, uid, [
            ('product_id', 'in', ids),
            ('location_id.usage', '!=', 'internal'),
            ('location_dest_id.usage', '=', 'internal'),
            ('state','in',('confirmed','assigned','pending'))
        ], ['product_id'], ['product_id'])
        for move in moves:
            product_id = move['product_id'][0]
            res[product_id]['reception_count'] = move['product_id_count']
        moves = move_pool.read_group(cr, uid, [
            ('product_id', 'in', ids),
            ('location_id.usage', '=', 'internal'),
            ('location_dest_id.usage', '!=', 'internal'),
            ('state','in',('confirmed','assigned','pending'))
        ], ['product_id'], ['product_id'])
        for move in moves:
            product_id = move['product_id'][0]
            res[product_id]['delivery_count'] = move['product_id_count']
        return res

    def view_header_get(self, cr, user, view_id, view_type, context=None):
        if context is None:
            context = {}
        res = super(product_product, self).view_header_get(cr, user, view_id, view_type, context)
        if res: return res
        if (context.get('active_id', False)) and (context.get('active_model') == 'stock.location'):
            return _('Products: ')+self.pool.get('stock.location').browse(cr, user, context['active_id'], context).name
        return res

    def _get_domain_locations(self, cr, uid, ids, context=None):
        '''
        Parses the context and returns a list of location_ids based on it.
        It will return all stock locations when no parameters are given
        Possible parameters are shop, warehouse, location, force_company, compute_child
        '''
        context = context or {}

        location_obj = self.pool.get('stock.location')
        warehouse_obj = self.pool.get('stock.warehouse')

        location_ids = []
        if context.get('location', False):
            if type(context['location']) == type(1):
                location_ids = [context['location']]
            elif type(context['location']) in (type(''), type(u'')):
                domain = [('complete_name','ilike',context['location'])]
                if context.get('force_company', False):
                    domain += [('company_id', '=', context['force_company'])]
                location_ids = location_obj.search(cr, uid, domain, context=context)
            else:
                location_ids = context['location']
        else:
            if context.get('warehouse', False):
                wids = [context['warehouse']]
            else:
                wids = warehouse_obj.search(cr, uid, [], context=context)

            for w in warehouse_obj.browse(cr, uid, wids, context=context):
                location_ids.append(w.view_location_id.id)

        operator = context.get('compute_child', True) and 'child_of' or 'in'
        domain = context.get('force_company', False) and ['&', ('company_id', '=', context['force_company'])] or []
        locations = location_obj.browse(cr, uid, location_ids, context=context)
        if operator == "child_of" and locations and locations[0].parent_left != 0:
            loc_domain = []
            dest_loc_domain = []
            for loc in locations:
                if loc_domain:
                    loc_domain = ['|'] + loc_domain  + ['&', ('location_id.parent_left', '>=', loc.parent_left), ('location_id.parent_left', '<', loc.parent_right)]
                    dest_loc_domain = ['|'] + dest_loc_domain + ['&', ('location_dest_id.parent_left', '>=', loc.parent_left), ('location_dest_id.parent_left', '<', loc.parent_right)]
                else:
                    loc_domain += ['&', ('location_id.parent_left', '>=', loc.parent_left), ('location_id.parent_left', '<', loc.parent_right)]
                    dest_loc_domain += ['&', ('location_dest_id.parent_left', '>=', loc.parent_left), ('location_dest_id.parent_left', '<', loc.parent_right)]

            return (
                domain + loc_domain,
                domain + ['&'] + dest_loc_domain + ['!'] + loc_domain,
                domain + ['&'] + loc_domain + ['!'] + dest_loc_domain
            )
        else:
            return (
                domain + [('location_id', operator, location_ids)],
                domain + ['&', ('location_dest_id', operator, location_ids), '!', ('location_id', operator, location_ids)],
                domain + ['&', ('location_id', operator, location_ids), '!', ('location_dest_id', operator, location_ids)]
            )

    def _get_domain_dates(self, cr, uid, ids, context):
        from_date = context.get('from_date', False)
        to_date = context.get('to_date', False)
        domain = []
        if from_date:
            domain.append(('date', '>=', from_date))
        if to_date:
            domain.append(('date', '<=', to_date))
        return domain

    def _product_available(self, cr, uid, ids, field_names=None, arg=False, context=None):
        context = context or {}
        field_names = field_names or []

        domain_products = [('product_id', 'in', ids)]
        domain_quant, domain_move_in, domain_move_out = [], [], []
        domain_quant_loc, domain_move_in_loc, domain_move_out_loc = self._get_domain_locations(cr, uid, ids, context=context)
        domain_move_in += self._get_domain_dates(cr, uid, ids, context=context) + [('state', 'not in', ('done', 'cancel', 'draft'))] + domain_products
        domain_move_out += self._get_domain_dates(cr, uid, ids, context=context) + [('state', 'not in', ('done', 'cancel', 'draft'))] + domain_products
        domain_quant += domain_products

        if context.get('lot_id'):
            domain_quant.append(('lot_id', '=', context['lot_id']))
        if context.get('owner_id'):
            domain_quant.append(('owner_id', '=', context['owner_id']))
            owner_domain = ('restrict_partner_id', '=', context['owner_id'])
            domain_move_in.append(owner_domain)
            domain_move_out.append(owner_domain)
        if context.get('package_id'):
            domain_quant.append(('package_id', '=', context['package_id']))

        domain_move_in += domain_move_in_loc
        domain_move_out += domain_move_out_loc
        moves_in = self.pool.get('stock.move').read_group(cr, uid, domain_move_in, ['product_id', 'product_qty'], ['product_id'], context=context)
        moves_out = self.pool.get('stock.move').read_group(cr, uid, domain_move_out, ['product_id', 'product_qty'], ['product_id'], context=context)

        domain_quant += domain_quant_loc
        quants = self.pool.get('stock.quant').read_group(cr, uid, domain_quant, ['product_id', 'qty'], ['product_id'], context=context)
        quants = dict(map(lambda x: (x['product_id'][0], x['qty']), quants))

        moves_in = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_in))
        moves_out = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_out))
        res = {}
        for product in self.browse(cr, uid, ids, context=context):
            id = product.id
            qty_available = float_round(quants.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            incoming_qty = float_round(moves_in.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            outgoing_qty = float_round(moves_out.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            virtual_available = float_round(quants.get(id, 0.0) + moves_in.get(id, 0.0) - moves_out.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            res[id] = {
                'qty_available': qty_available,
                'incoming_qty': incoming_qty,
                'outgoing_qty': outgoing_qty,
                'virtual_available': virtual_available,
            }
        return res

    def _search_product_quantity(self, cr, uid, obj, name, domain, context):
        res = []
        for field, operator, value in domain:
            #to prevent sql injections
            assert field in ('qty_available', 'virtual_available', 'incoming_qty', 'outgoing_qty'), 'Invalid domain left operand'
            assert operator in ('<', '>', '=', '!=', '<=', '>='), 'Invalid domain operator'
            assert isinstance(value, (float, int)), 'Invalid domain right operand'

            if operator == '=':
                operator = '=='

            ids = []
            if name == 'qty_available' and (value != 0.0 or operator not in  ('==', '>=', '<=')):
                res.append(('id', 'in', self._search_qty_available(cr, uid, operator, value, context)))
            else:
                product_ids = self.search(cr, uid, [], context=context)
                if product_ids:
                    #TODO: Still optimization possible when searching virtual quantities
                    for element in self.browse(cr, uid, product_ids, context=context):
                        if eval(str(element[field]) + operator + str(value)):
                            ids.append(element.id)
                    res.append(('id', 'in', ids))
        return res

    def _search_qty_available(self, cr, uid, operator, value, context):
        domain_quant = []
        if context.get('lot_id'):
            domain_quant.append(('lot_id', '=', context['lot_id']))
        if context.get('owner_id'):
            domain_quant.append(('owner_id', '=', context['owner_id']))
        if context.get('package_id'):
            domain_quant.append(('package_id', '=', context['package_id']))
        domain_quant += self._get_domain_locations(cr, uid, [], context=context)[0]
        quants = self.pool.get('stock.quant').read_group(cr, uid, domain_quant, ['product_id', 'qty'], ['product_id'], context=context)
        quants = dict(map(lambda x: (x['product_id'][0], x['qty']), quants))
        quants = dict((k, v) for k, v in quants.iteritems() if eval(str(v) + operator + str(value)))
        return(list(quants))

    def _product_available_text(self, cr, uid, ids, field_names=None, arg=False, context=None):
        res = {}
        for product in self.browse(cr, uid, ids, context=context):
            res[product.id] = str(product.qty_available) +  _(" On Hand")
        return res

    _columns = {
        'reception_count': fields.function(_stock_move_count, string="Receipt", type='integer', multi='pickings'),
        'delivery_count': fields.function(_stock_move_count, string="Delivery", type='integer', multi='pickings'),
        'qty_available_text': fields.function(_product_available_text, type='char'),
        'qty_available': fields.function(_product_available, multi='qty_available',
            type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
            string='Quantity On Hand',
            fnct_search=_search_product_quantity,
            help="Current quantity of products.\n"
                 "In a context with a single Stock Location, this includes "
                 "goods stored at this Location, or any of its children.\n"
                 "In a context with a single Warehouse, this includes "
                 "goods stored in the Stock Location of this Warehouse, or any "
                 "of its children.\n"
                 "stored in the Stock Location of the Warehouse of this Shop, "
                 "or any of its children.\n"
                 "Otherwise, this includes goods stored in any Stock Location "
                 "with 'internal' type."),
        'virtual_available': fields.function(_product_available, multi='qty_available',
            type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
            string='Forecast Quantity',
            fnct_search=_search_product_quantity,
            help="Forecast quantity (computed as Quantity On Hand "
                 "- Outgoing + Incoming)\n"
                 "In a context with a single Stock Location, this includes "
                 "goods stored in this location, or any of its children.\n"
                 "In a context with a single Warehouse, this includes "
                 "goods stored in the Stock Location of this Warehouse, or any "
                 "of its children.\n"
                 "Otherwise, this includes goods stored in any Stock Location "
                 "with 'internal' type."),
        'incoming_qty': fields.function(_product_available, multi='qty_available',
            type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
            string='Incoming',
            fnct_search=_search_product_quantity,
            help="Quantity of products that are planned to arrive.\n"
                 "In a context with a single Stock Location, this includes "
                 "goods arriving to this Location, or any of its children.\n"
                 "In a context with a single Warehouse, this includes "
                 "goods arriving to the Stock Location of this Warehouse, or "
                 "any of its children.\n"
                 "Otherwise, this includes goods arriving to any Stock "
                 "Location with 'internal' type."),
        'outgoing_qty': fields.function(_product_available, multi='qty_available',
            type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
            string='Outgoing',
            fnct_search=_search_product_quantity,
            help="Quantity of products that are planned to leave.\n"
                 "In a context with a single Stock Location, this includes "
                 "goods leaving this Location, or any of its children.\n"
                 "In a context with a single Warehouse, this includes "
                 "goods leaving the Stock Location of this Warehouse, or "
                 "any of its children.\n"
                 "Otherwise, this includes goods leaving any Stock "
                 "Location with 'internal' type."),
        'location_id': fields.dummy(string='Location', relation='stock.location', type='many2one'),
        'warehouse_id': fields.dummy(string='Warehouse', relation='stock.warehouse', type='many2one'),
        'orderpoint_ids': fields.one2many('stock.warehouse.orderpoint', 'product_id', 'Minimum Stock Rules'),
    }

    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
        res = super(product_product,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
        if context is None:
            context = {}
        if ('location' in context) and context['location']:
            location_info = self.pool.get('stock.location').browse(cr, uid, context['location'])
            fields=res.get('fields',{})
            if fields:
                if location_info.usage == 'supplier':
                    if fields.get('virtual_available'):
                        res['fields']['virtual_available']['string'] = _('Future Receipts')
                    if fields.get('qty_available'):
                        res['fields']['qty_available']['string'] = _('Received Qty')

                if location_info.usage == 'internal':
                    if fields.get('virtual_available'):
                        res['fields']['virtual_available']['string'] = _('Future Stock')

                if location_info.usage == 'customer':
                    if fields.get('virtual_available'):
                        res['fields']['virtual_available']['string'] = _('Future Deliveries')
                    if fields.get('qty_available'):
                        res['fields']['qty_available']['string'] = _('Delivered Qty')

                if location_info.usage == 'inventory':
                    if fields.get('virtual_available'):
                        res['fields']['virtual_available']['string'] = _('Future P&L')
                    if fields.get('qty_available'):
                        res['fields']['qty_available']['string'] = _('P&L Qty')

                if location_info.usage == 'procurement':
                    if fields.get('virtual_available'):
                        res['fields']['virtual_available']['string'] = _('Future Qty')
                    if fields.get('qty_available'):
                        res['fields']['qty_available']['string'] = _('Unplanned Qty')

                if location_info.usage == 'production':
                    if fields.get('virtual_available'):
                        res['fields']['virtual_available']['string'] = _('Future Productions')
                    if fields.get('qty_available'):
                        res['fields']['qty_available']['string'] = _('Produced Qty')
        return res


    def action_view_routes(self, cr, uid, ids, context=None):
        template_obj = self.pool.get("product.template")
        templ_ids = list(set([x.product_tmpl_id.id for x in self.browse(cr, uid, ids, context=context)]))
        return template_obj.action_view_routes(cr, uid, templ_ids, context=context)