示例#1
0
 def do_produce(self):
     # Nothing to do for lots since values are created using default data (stock.move.lots)
     quantity = self.product_qty
     if float_compare(quantity, 0, precision_rounding=self.product_uom_id.rounding) <= 0:
         raise UserError(_("The production order for '%s' has no quantity specified") % self.product_id.display_name)
     for move in self.production_id.move_raw_ids:
         # TODO currently not possible to guess if the user updated quantity by hand or automatically by the produce wizard.
         if move.product_id.tracking == 'none' and move.state not in ('done', 'cancel') and move.unit_factor:
             rounding = move.product_uom.rounding
             if self.product_id.tracking != 'none':
                 qty_to_add = float_round(quantity * move.unit_factor, precision_rounding=rounding)
                 move._generate_consumed_move_line(qty_to_add, self.lot_id)
             elif len(move._get_move_lines()) < 2:
                 move.quantity_done += float_round(quantity * move.unit_factor, precision_rounding=rounding)
             else:
                 move._set_quantity_done(quantity * move.unit_factor)
     for move in self.production_id.move_finished_ids:
         if move.product_id.tracking == 'none' and move.state not in ('done', 'cancel'):
             rounding = move.product_uom.rounding
             if move.product_id.id == self.production_id.product_id.id:
                 move.quantity_done += float_round(quantity, precision_rounding=rounding)
             elif move.unit_factor:
                 # byproducts handling
                 move.quantity_done += float_round(quantity * move.unit_factor, precision_rounding=rounding)
     self.check_finished_move_lots()
     if self.production_id.state == 'confirmed':
         self.production_id.write({
             'state': 'progress',
             'date_start': datetime.now(),
         })
     return {'type': 'ir.actions.act_window_close'}
示例#2
0
 def check_finished_move_lots(self):
     """ Handle by product tracked """
     by_product_moves = self.production_id.move_finished_ids.filtered(
         lambda m: m.product_id != self.product_id and m.product_id.tracking
         != 'none' and m.state not in ('done', 'cancel'))
     for by_product_move in by_product_moves:
         rounding = by_product_move.product_uom.rounding
         quantity = float_round(self.product_qty *
                                by_product_move.unit_factor,
                                precision_rounding=rounding)
         values = {
             'move_id': by_product_move.id,
             'product_id': by_product_move.product_id.id,
             'production_id': self.production_id.id,
             'product_uom_id': by_product_move.product_uom.id,
             'location_id': by_product_move.location_id.id,
             'location_dest_id': by_product_move.location_dest_id.id,
         }
         if by_product_move.product_id.tracking == 'lot':
             values.update({
                 'product_uom_qty': quantity,
                 'qty_done': quantity,
             })
             self.env['stock.move.line'].create(values)
         else:
             values.update({
                 'product_uom_qty': 1.0,
                 'qty_done': 1.0,
             })
             for i in range(0, int(quantity)):
                 self.env['stock.move.line'].create(values)
     return super(MrpProductProduce, self).check_finished_move_lots()
    def create(self, values):
        if values.get('partner_id'):  # @TDENOTE: not sure
            values.update(
                self.on_change_partner_id(values['partner_id'])['value'])

        # call custom create method if defined (i.e. ogone_create for ogone)
        if values.get('acquirer_id'):
            acquirer = self.env['payment.acquirer'].browse(
                values['acquirer_id'])

            # compute fees
            custom_method_name = '%s_compute_fees' % acquirer.provider
            if hasattr(acquirer, custom_method_name):
                fees = getattr(acquirer, custom_method_name)(
                    values.get('amount', 0.0), values.get('currency_id'),
                    values.get('partner_country_id'))
                values['fees'] = float_round(fees, 2)

            # custom create
            custom_method_name = '%s_create' % acquirer.provider
            if hasattr(acquirer, custom_method_name):
                values.update(getattr(self, custom_method_name)(values))

        # Default value of reference is
        tx = super(PaymentTransaction, self).create(values)
        if not values.get('reference'):
            tx.write({'reference': str(tx.id)})

        # Generate callback hash if it is configured on the tx; avoid generating unnecessary stuff
        # (limited sudo env for checking callback presence, must work for manual transactions too)
        tx_sudo = tx.sudo()
        if tx_sudo.callback_model_id and tx_sudo.callback_res_id and tx_sudo.callback_method:
            tx.write({'callback_hash': tx._generate_callback_hash()})

        return tx
示例#4
0
 def _get_price(self, pricelist, product, qty):
     sale_price_digits = self.env['decimal.precision'].precision_get(
         'Product Price')
     price = pricelist.get_product_price(product, qty, False)
     if not price:
         price = product.list_price
     return float_round(price, precision_digits=sale_price_digits)
    def round(self, amount):
        """Compute the rounding on the amount passed as parameter.

        :param amount: the amount to round
        :return: the rounded amount depending the rounding value and the rounding method
        """
        return float_round(amount,
                           precision_rounding=self.rounding,
                           rounding_method=self.rounding_method)
示例#6
0
 def _compute_quantity(self, qty, to_unit, round=True, rounding_method='UP'):
     if not self:
         return qty
     self.ensure_one()
     if self.category_id.id != to_unit.category_id.id:
         if self._context.get('raise-exception', True):
             raise UserError(_('Conversion from Product UoM %s to Default UoM %s is not possible as they both belong to different Category!.') % (self.name, to_unit.name))
         else:
             return qty
     amount = qty / self.factor
     if to_unit:
         amount = amount * to_unit.factor
         if round:
             amount = tools.float_round(amount, precision_rounding=to_unit.rounding, rounding_method=rounding_method)
     return amount
 def write(self, values):
     if ('acquirer_id' in values
             or 'amount' in values) and 'fees' not in values:
         # The acquirer or the amount has changed, and the fees are not explicitly forced. Fees must be recomputed.
         acquirer = None
         if values.get('acquirer_id'):
             acquirer = self.env['payment.acquirer'].browse(
                 values['acquirer_id'])
         for tx in self:
             vals = dict(values, fees=0.0)
             if not acquirer:
                 acquirer = tx.acquirer_id
             custom_method_name = '%s_compute_fees' % acquirer.provider
             # TDE FIXME: shouldn't we use fee_implemented ?
             if hasattr(acquirer, custom_method_name):
                 fees = getattr(acquirer, custom_method_name)(
                     (values['amount'] if 'amount' in values else tx.amount)
                     or 0.0, values.get('currency_id') or tx.currency_id.id,
                     values.get('partner_country_id')
                     or tx.partner_country_id.id)
                 vals['fees'] = float_round(fees, 2)
             res = super(PaymentTransaction, tx).write(vals)
         return res
     return super(PaymentTransaction, self).write(values)
示例#8
0
    def _procure_orderpoint_confirm(self,
                                    use_new_cursor=False,
                                    company_id=False):
        """ Create procurements based on orderpoints.
        :param bool use_new_cursor: if set, use a dedicated cursor and auto-commit after processing
            1000 orderpoints.
            This is appropriate for batch jobs only.
        """
        if company_id and self.env.user.company_id.id != company_id:
            # To ensure that the company_id is taken into account for
            # all the processes triggered by this method
            # i.e. If a PO is generated by the run of the procurements the
            # sequence to use is the one for the specified company not the
            # one of the user's company
            self = self.with_context(company_id=company_id,
                                     force_company=company_id)
        OrderPoint = self.env['stock.warehouse.orderpoint']
        domain = self._get_orderpoint_domain(company_id=company_id)
        orderpoints_noprefetch = OrderPoint.with_context(
            prefetch_fields=False).search(
                domain,
                order=self._procurement_from_orderpoint_get_order()).ids
        while orderpoints_noprefetch:
            if use_new_cursor:
                cr = registry(self._cr.dbname).cursor()
                self = self.with_env(self.env(cr=cr))
            OrderPoint = self.env['stock.warehouse.orderpoint']

            orderpoints = OrderPoint.browse(orderpoints_noprefetch[:1000])
            orderpoints_noprefetch = orderpoints_noprefetch[1000:]

            # Calculate groups that can be executed together
            location_data = OrderedDict()

            def makedefault():
                return {
                    'products': self.env['product.product'],
                    'orderpoints': self.env['stock.warehouse.orderpoint'],
                    'groups': []
                }

            for orderpoint in orderpoints:
                key = self._procurement_from_orderpoint_get_grouping_key(
                    [orderpoint.id])
                if not location_data.get(key):
                    location_data[key] = makedefault()
                location_data[key]['products'] += orderpoint.product_id
                location_data[key]['orderpoints'] += orderpoint
                location_data[key][
                    'groups'] = self._procurement_from_orderpoint_get_groups(
                        [orderpoint.id])

            for location_id, location_data in location_data.items():
                location_orderpoints = location_data['orderpoints']
                product_context = dict(
                    self._context,
                    location=location_orderpoints[0].location_id.id)
                substract_quantity = location_orderpoints._quantity_in_progress(
                )

                for group in location_data['groups']:
                    if group.get('from_date'):
                        product_context['from_date'] = group[
                            'from_date'].strftime(
                                DEFAULT_SERVER_DATETIME_FORMAT)
                    if group['to_date']:
                        product_context['to_date'] = group['to_date'].strftime(
                            DEFAULT_SERVER_DATETIME_FORMAT)
                    product_quantity = location_data['products'].with_context(
                        product_context)._product_available()
                    for orderpoint in location_orderpoints:
                        try:
                            op_product_virtual = product_quantity[
                                orderpoint.product_id.id]['virtual_available']
                            if op_product_virtual is None:
                                continue
                            if float_compare(op_product_virtual,
                                             orderpoint.product_min_qty,
                                             precision_rounding=orderpoint.
                                             product_uom.rounding) <= 0:
                                qty = max(orderpoint.product_min_qty,
                                          orderpoint.product_max_qty
                                          ) - op_product_virtual
                                remainder = orderpoint.qty_multiple > 0 and qty % orderpoint.qty_multiple or 0.0

                                if float_compare(remainder,
                                                 0.0,
                                                 precision_rounding=orderpoint.
                                                 product_uom.rounding) > 0:
                                    qty += orderpoint.qty_multiple - remainder

                                if float_compare(qty,
                                                 0.0,
                                                 precision_rounding=orderpoint.
                                                 product_uom.rounding) < 0:
                                    continue

                                qty -= substract_quantity[orderpoint.id]
                                qty_rounded = float_round(
                                    qty,
                                    precision_rounding=orderpoint.product_uom.
                                    rounding)
                                if qty_rounded > 0:
                                    values = orderpoint._prepare_procurement_values(
                                        qty_rounded,
                                        **group['procurement_values'])
                                    try:
                                        with self._cr.savepoint():
                                            self.env['procurement.group'].run(
                                                orderpoint.product_id,
                                                qty_rounded,
                                                orderpoint.product_uom,
                                                orderpoint.location_id,
                                                orderpoint.name,
                                                orderpoint.name, values)
                                    except UserError as error:
                                        self.env[
                                            'procurement.rule']._log_next_activity(
                                                orderpoint.product_id,
                                                error.name)
                                    self._procurement_from_orderpoint_post_process(
                                        [orderpoint.id])
                                if use_new_cursor:
                                    cr.commit()

                        except OperationalError:
                            if use_new_cursor:
                                orderpoints_noprefetch += [orderpoint.id]
                                cr.rollback()
                                continue
                            else:
                                raise

            try:
                if use_new_cursor:
                    cr.commit()
            except OperationalError:
                if use_new_cursor:
                    cr.rollback()
                    continue
                else:
                    raise

            if use_new_cursor:
                cr.commit()
                cr.close()

        return {}
示例#9
0
    def explode(self, product, quantity, picking_type=False):
        """
            Explodes the BoM and creates two lists with all the information you need: bom_done and line_done
            Quantity describes the number of times you need the BoM: so the quantity divided by the number created by the BoM
            and converted into its UoM
        """
        from collections import defaultdict

        graph = defaultdict(list)
        V = set()

        def check_cycle(v, visited, recStack, graph):
            visited[v] = True
            recStack[v] = True
            for neighbour in graph[v]:
                if visited[neighbour] == False:
                    if check_cycle(neighbour, visited, recStack,
                                   graph) == True:
                        return True
                elif recStack[neighbour] == True:
                    return True
            recStack[v] = False
            return False

        boms_done = [(self, {
            'qty': quantity,
            'product': product,
            'original_qty': quantity,
            'parent_line': False
        })]
        lines_done = []
        V |= set([product.product_tmpl_id.id])

        bom_lines = [(bom_line, product, quantity, False)
                     for bom_line in self.bom_line_ids]
        for bom_line in self.bom_line_ids:
            V |= set([bom_line.product_id.product_tmpl_id.id])
            graph[product.product_tmpl_id.id].append(
                bom_line.product_id.product_tmpl_id.id)
        while bom_lines:
            current_line, current_product, current_qty, parent_line = bom_lines[
                0]
            bom_lines = bom_lines[1:]

            if current_line._skip_bom_line(current_product):
                continue

            line_quantity = current_qty * current_line.product_qty
            bom = self._bom_find(product=current_line.product_id,
                                 picking_type=picking_type
                                 or self.picking_type_id,
                                 company_id=self.company_id.id)
            if bom.type == 'phantom':
                converted_line_quantity = current_line.product_uom_id._compute_quantity(
                    line_quantity / bom.product_qty, bom.product_uom_id)
                bom_lines = [(line, current_line.product_id,
                              converted_line_quantity, current_line)
                             for line in bom.bom_line_ids] + bom_lines
                for bom_line in bom.bom_line_ids:
                    graph[current_line.product_id.product_tmpl_id.id].append(
                        bom_line.product_id.product_tmpl_id.id)
                    if bom_line.product_id.product_tmpl_id.id in V and check_cycle(
                            bom_line.product_id.product_tmpl_id.id,
                        {key: False
                         for key in V}, {key: False
                                         for key in V}, graph):
                        raise UserError(
                            _('Recursion error!  A product with a Bill of Material should not have itself in its BoM or child BoMs!'
                              ))
                    V |= set([bom_line.product_id.product_tmpl_id.id])
                boms_done.append((bom, {
                    'qty': converted_line_quantity,
                    'product': current_product,
                    'original_qty': quantity,
                    'parent_line': current_line
                }))
            else:
                # We round up here because the user expects that if he has to consume a little more, the whole UOM unit
                # should be consumed.
                rounding = current_line.product_uom_id.rounding
                line_quantity = float_round(line_quantity,
                                            precision_rounding=rounding,
                                            rounding_method='UP')
                lines_done.append((current_line, {
                    'qty': line_quantity,
                    'product': current_product,
                    'original_qty': quantity,
                    'parent_line': parent_line
                }))

        return boms_done, lines_done
示例#10
0
    def _prepare_plan_values(self, domain):

        timesheet_lines = request.env['account.analytic.line'].search(domain)
        currency = request.env.user.company_id.currency_id

        values = {
            'currency': currency,
            'timesheet_lines': timesheet_lines,
            'domain': domain,
        }
        hour_rounding = request.env.ref('product.product_uom_hour').rounding
        billable_types = [
            'non_billable', 'non_billable_project', 'billable_time',
            'billable_fixed'
        ]

        # -- Stat Buttons
        values['stat_buttons'] = self._plan_get_stat_button(timesheet_lines)

        # -- Dashboard (per billable type)
        dashboard_values = {
            'hours': dict.fromkeys(billable_types + ['total'], 0.0),
            'rates': dict.fromkeys(billable_types + ['total'], 0.0),
            'money_amount': {
                'invoiced': 0.0,
                'to_invoice': 0.0,
                'cost': 0.0,
                'total': 0.0,
            }
        }
        dashboard_domain = domain + [('timesheet_invoice_type', '!=', False)
                                     ]  # force billable type
        dashboard_data = request.env['account.analytic.line'].read_group(
            dashboard_domain,
            ['unit_amount', 'timesheet_revenue', 'timesheet_invoice_type'],
            ['timesheet_invoice_type'])

        dashboard_total_hours = sum(
            [data['unit_amount'] for data in dashboard_data])
        for data in dashboard_data:
            billable_type = data['timesheet_invoice_type']
            # hours
            dashboard_values['hours'][billable_type] = float_round(
                data.get('unit_amount'), precision_rounding=hour_rounding)
            dashboard_values['hours']['total'] += float_round(
                data.get('unit_amount'), precision_rounding=hour_rounding)
            # rates
            dashboard_values['rates'][
                billable_type] = dashboard_total_hours and round(
                    data.get('unit_amount') / dashboard_total_hours * 100,
                    2) or 0
            dashboard_values['rates'][
                'total'] += dashboard_total_hours and round(
                    data.get('unit_amount') / dashboard_total_hours * 100,
                    2) or 0

        # money_amount
        so_lines = values['timesheet_lines'].mapped('so_line')
        invoice_lines = so_lines.mapped('invoice_lines')
        dashboard_values['money_amount']['invoiced'] = sum([
            inv_line.currency_id.with_context(
                date=inv_line.invoice_id.date_invoice).compute(
                    inv_line.price_unit * inv_line.quantity, currency)
            for inv_line in invoice_lines.filtered(
                lambda line: line.invoice_id.state in ['open', 'paid'])
        ])
        dashboard_values['money_amount']['to_invoice'] = sum([
            sol.currency_id.compute(
                sol.price_unit *
                (1 -
                 (sol.discount or 0.0) / 100.0) * sol.qty_to_invoice, currency)
            for sol in so_lines
        ]) + sum([
            i.currency_id.with_context(date=i.invoice_id.date_invoice).compute(
                i.price_unit * i.quantity, currency)
            for i in invoice_lines.filtered(
                lambda line: line.invoice_id.state == 'draft')
        ])
        dashboard_values['money_amount']['cost'] = sum(
            values['timesheet_lines'].mapped('amount'))
        dashboard_values['money_amount']['total'] = sum([
            dashboard_values['money_amount'][item]
            for item in dashboard_values['money_amount'].keys()
        ])

        values['dashboard'] = dashboard_values

        # -- Time Repartition (per employee)
        repartition_domain = domain + [('employee_id', '!=', False),
                                       ('timesheet_invoice_type', '!=', False)
                                       ]  # force billable type
        repartition_data = request.env['account.analytic.line'].read_group(
            repartition_domain,
            ['employee_id', 'timesheet_invoice_type', 'unit_amount'],
            ['employee_id', 'timesheet_invoice_type'],
            lazy=False)

        # set repartition per type per employee
        repartition_employee = {}
        for data in repartition_data:
            employee_id = data['employee_id'][0]
            repartition_employee.setdefault(
                employee_id,
                dict(
                    employee_id=data['employee_id'][0],
                    employee_name=data['employee_id'][1],
                    non_billable_project=0.0,
                    non_billable=0.0,
                    billable_time=0.0,
                    billable_fixed=0.0,
                    total=0.0,
                ))[data['timesheet_invoice_type']] = float_round(
                    data.get('unit_amount', 0.0),
                    precision_rounding=hour_rounding)
            repartition_employee[employee_id][
                '__domain_' +
                data['timesheet_invoice_type']] = data['__domain']

        # compute total
        for employee_id, vals in repartition_employee.items():
            repartition_employee[employee_id]['total'] = sum(
                [vals[inv_type] for inv_type in billable_types])

        hours_per_employee = [
            repartition_employee[employee_id]['total']
            for employee_id in repartition_employee
        ]
        values['repartition_employee_max'] = max(
            hours_per_employee) if hours_per_employee else 1
        values['repartition_employee'] = repartition_employee

        return values
示例#11
0
    def compute_landed_cost(self):
        AdjustementLines = self.env['stock.valuation.adjustment.lines']
        AdjustementLines.search([('cost_id', 'in', self.ids)]).unlink()

        digits = dp.get_precision('Product Price')(self._cr)
        towrite_dict = {}
        for cost in self.filtered(lambda cost: cost.picking_ids):
            total_qty = 0.0
            total_cost = 0.0
            total_weight = 0.0
            total_volume = 0.0
            total_line = 0.0
            all_val_line_values = cost.get_valuation_lines()
            for val_line_values in all_val_line_values:
                for cost_line in cost.cost_lines:
                    val_line_values.update({'cost_id': cost.id, 'cost_line_id': cost_line.id})
                    self.env['stock.valuation.adjustment.lines'].create(val_line_values)
                total_qty += val_line_values.get('quantity', 0.0)
                total_weight += val_line_values.get('weight', 0.0)
                total_volume += val_line_values.get('volume', 0.0)

                former_cost = val_line_values.get('former_cost', 0.0)
                # round this because former_cost on the valuation lines is also rounded
                total_cost += tools.float_round(former_cost, precision_digits=digits[1]) if digits else former_cost

                total_line += 1

            for line in cost.cost_lines:
                value_split = 0.0
                for valuation in cost.valuation_adjustment_lines:
                    value = 0.0
                    if valuation.cost_line_id and valuation.cost_line_id.id == line.id:
                        if line.split_method == 'by_quantity' and total_qty:
                            per_unit = (line.price_unit / total_qty)
                            value = valuation.quantity * per_unit
                        elif line.split_method == 'by_weight' and total_weight:
                            per_unit = (line.price_unit / total_weight)
                            value = valuation.weight * per_unit
                        elif line.split_method == 'by_volume' and total_volume:
                            per_unit = (line.price_unit / total_volume)
                            value = valuation.volume * per_unit
                        elif line.split_method == 'equal':
                            value = (line.price_unit / total_line)
                        elif line.split_method == 'by_current_cost_price' and total_cost:
                            per_unit = (line.price_unit / total_cost)
                            value = valuation.former_cost * per_unit
                        else:
                            value = (line.price_unit / total_line)

                        if digits:
                            value = tools.float_round(value, precision_digits=digits[1], rounding_method='UP')
                            fnc = min if line.price_unit > 0 else max
                            value = fnc(value, line.price_unit - value_split)
                            value_split += value

                        if valuation.id not in towrite_dict:
                            towrite_dict[valuation.id] = value
                        else:
                            towrite_dict[valuation.id] += value
        for key, value in towrite_dict.items():
            AdjustementLines.browse(key).write({'additional_landed_cost': value})
        return True
示例#12
0
    def adyen_form_generate_values(self, values):
        base_url = self.env['ir.config_parameter'].sudo().get_param(
            'web.base.url')
        # tmp
        import datetime
        from dateutil import relativedelta

        if self.provider == 'adyen' and len(self.adyen_skin_hmac_key) == 64:
            tmp_date = datetime.datetime.today() + relativedelta.relativedelta(
                days=1)

            values.update({
                'merchantReference':
                values['reference'],
                'paymentAmount':
                '%d' % int(tools.float_round(values['amount'], 2) * 100),
                'currencyCode':
                values['currency'] and values['currency'].name or '',
                'shipBeforeDate':
                tmp_date.strftime('%Y-%m-%d'),
                'skinCode':
                self.adyen_skin_code,
                'merchantAccount':
                self.adyen_merchant_account,
                'shopperLocale':
                values.get('partner_lang', ''),
                'sessionValidity':
                tmp_date.isoformat('T')[:19] + "Z",
                'resURL':
                urls.url_join(base_url, AdyenController._return_url),
                'merchantReturnData':
                json.dumps({'return_url': '%s' % values.pop('return_url')})
                if values.get('return_url', '') else False,
                'shopperEmail':
                values.get('partner_email', ''),
            })
            values['merchantSig'] = self._adyen_generate_merchant_sig_sha256(
                'in', values)

        else:
            tmp_date = datetime.date.today() + relativedelta.relativedelta(
                days=1)

            values.update({
                'merchantReference':
                values['reference'],
                'paymentAmount':
                '%d' % int(tools.float_round(values['amount'], 2) * 100),
                'currencyCode':
                values['currency'] and values['currency'].name or '',
                'shipBeforeDate':
                tmp_date,
                'skinCode':
                self.adyen_skin_code,
                'merchantAccount':
                self.adyen_merchant_account,
                'shopperLocale':
                values.get('partner_lang'),
                'sessionValidity':
                tmp_date,
                'resURL':
                urls.url_join(base_url, AdyenController._return_url),
                'merchantReturnData':
                json.dumps({'return_url': '%s' % values.pop('return_url')})
                if values.get('return_url') else False,
            })
            values['merchantSig'] = self._adyen_generate_merchant_sig(
                'in', values)

        return values
示例#13
0
    def default_get(self, fields):
        res = super(MrpProductProduce, self).default_get(fields)
        if self._context and self._context.get('active_id'):
            production = self.env['mrp.production'].browse(self._context['active_id'])
            serial_finished = (production.product_id.tracking == 'serial')
            if serial_finished:
                todo_quantity = 1.0
            else:
                main_product_moves = production.move_finished_ids.filtered(lambda x: x.product_id.id == production.product_id.id)
                todo_quantity = production.product_qty - sum(main_product_moves.mapped('quantity_done'))
                todo_quantity = todo_quantity if (todo_quantity > 0) else 0
            if 'production_id' in fields:
                res['production_id'] = production.id
            if 'product_id' in fields:
                res['product_id'] = production.product_id.id
            if 'product_uom_id' in fields:
                res['product_uom_id'] = production.product_uom_id.id
            if 'serial' in fields:
                res['serial'] = bool(serial_finished)
            if 'product_qty' in fields:
                res['product_qty'] = todo_quantity
            if 'produce_line_ids' in fields:
                lines = []
                for move in production.move_raw_ids.filtered(lambda x: (x.product_id.tracking != 'none') and x.state not in ('done', 'cancel') and x.bom_line_id):
                    qty_to_consume = float_round(todo_quantity / move.bom_line_id.bom_id.product_qty * move.bom_line_id.product_qty,
                                                 precision_rounding=move.product_uom.rounding, rounding_method="UP")
                    for move_line in move.move_line_ids:
                        if float_compare(qty_to_consume, 0.0, precision_rounding=move.product_uom.rounding) <= 0:
                            break
                        if move_line.lot_produced_id or float_compare(move_line.product_uom_qty, move_line.qty_done, precision_rounding=move.product_uom.rounding) <= 0:
                            continue
                        to_consume_in_line = min(qty_to_consume, move_line.product_uom_qty)
                        lines.append({
                            'move_id': move.id,
                            'qty_to_consume': to_consume_in_line,
                            'qty_done': 0.0,
                            'lot_id': move_line.lot_id.id,
                            'product_uom_id': move.product_uom.id,
                            'product_id': move.product_id.id,
                        })
                        qty_to_consume -= to_consume_in_line
                    if float_compare(qty_to_consume, 0.0, precision_rounding=move.product_uom.rounding) > 0:
                        if move.product_id.tracking == 'serial':
                            while float_compare(qty_to_consume, 0.0, precision_rounding=move.product_uom.rounding) > 0:
                                lines.append({
                                    'move_id': move.id,
                                    'qty_to_consume': 1,
                                    'qty_done': 0.0,
                                    'product_uom_id': move.product_uom.id,
                                    'product_id': move.product_id.id,
                                })
                                qty_to_consume -= 1
                        else:
                            lines.append({
                                'move_id': move.id,
                                'qty_to_consume': qty_to_consume,
                                'qty_done': 0.0,
                                'product_uom_id': move.product_uom.id,
                                'product_id': move.product_id.id,
                            })

                res['produce_line_ids'] = [(0, 0, x) for x in lines]
        return res
示例#14
0
    def _run_valuation(self, quantity=None):
        self.ensure_one()
        if self._is_in():
            valued_move_lines = self.move_line_ids.filtered(
                lambda ml: not ml.location_id._should_be_valued() and ml.
                location_dest_id._should_be_valued() and not ml.owner_id)
            valued_quantity = 0
            for valued_move_line in valued_move_lines:
                valued_quantity += valued_move_line.product_uom_id._compute_quantity(
                    valued_move_line.qty_done, self.product_id.uom_id)

            # Note: we always compute the fifo `remaining_value` and `remaining_qty` fields no
            # matter which cost method is set, to ease the switching of cost method.
            vals = {}
            price_unit = self._get_price_unit()
            value = price_unit * (quantity or valued_quantity)
            vals = {
                'price_unit':
                price_unit,
                'value':
                value if quantity is None or not self.value else self.value,
                'remaining_value':
                value if quantity is None else self.remaining_value + value,
            }
            vals[
                'remaining_qty'] = valued_quantity if quantity is None else self.remaining_qty + quantity

            if self.product_id.cost_method == 'standard':
                value = self.product_id.standard_price * (quantity
                                                          or valued_quantity)
                vals.update({
                    'price_unit':
                    self.product_id.standard_price,
                    'value':
                    value
                    if quantity is None or not self.value else self.value,
                })
            self.write(vals)
        elif self._is_out():
            valued_move_lines = self.move_line_ids.filtered(
                lambda ml: ml.location_id._should_be_valued() and not ml.
                location_dest_id._should_be_valued() and not ml.owner_id)
            valued_quantity = 0
            for valued_move_line in valued_move_lines:
                valued_quantity += valued_move_line.product_uom_id._compute_quantity(
                    valued_move_line.qty_done, self.product_id.uom_id)
            self.env['stock.move']._run_fifo(self, quantity=quantity)
            if self.product_id.cost_method in ['standard', 'average']:
                curr_rounding = self.company_id.currency_id.rounding
                value = -float_round(
                    self.product_id.standard_price *
                    (valued_quantity if quantity is None else quantity),
                    precision_rounding=curr_rounding)
                self.write({
                    'value':
                    value if quantity is None else self.value + value,
                    'price_unit':
                    value / valued_quantity,
                })
        elif self._is_dropshipped() or self._is_dropshipped_returned():
            curr_rounding = self.company_id.currency_id.rounding
            if self.product_id.cost_method in ['fifo']:
                price_unit = self._get_price_unit()
                # see test_dropship_fifo_perpetual_anglosaxon_ordered
                self.product_id.standard_price = price_unit
            else:
                price_unit = self.product_id.standard_price
            value = float_round(self.product_qty * price_unit,
                                precision_rounding=curr_rounding)
            # In move have a positive value, out move have a negative value, let's arbitrary say
            # dropship are positive.
            self.write({
                'value':
                value if self._is_dropshipped() else -value,
                'price_unit':
                price_unit if self._is_dropshipped() else -price_unit,
            })
示例#15
0
    def render(self,
               reference,
               amount,
               currency_id,
               partner_id=False,
               values=None):
        """ Renders the form template of the given acquirer as a qWeb template.
        :param string reference: the transaction reference
        :param float amount: the amount the buyer has to pay
        :param currency_id: currency id
        :param dict partner_id: optional partner_id to fill values
        :param dict values: a dictionary of values for the transction that is
        given to the acquirer-specific method generating the form values

        All templates will receive:

         - acquirer: the payment.acquirer browse record
         - user: the current user browse record
         - currency_id: id of the transaction currency
         - amount: amount of the transaction
         - reference: reference of the transaction
         - partner_*: partner-related values
         - partner: optional partner browse record
         - 'feedback_url': feedback URL, controler that manage answer of the acquirer (without base url) -> FIXME
         - 'return_url': URL for coming back after payment validation (wihout base url) -> FIXME
         - 'cancel_url': URL if the client cancels the payment -> FIXME
         - 'error_url': URL if there is an issue with the payment -> FIXME
         - context: NobleCRM context

        """
        if values is None:
            values = {}

        # reference and amount
        values.setdefault('reference', reference)
        amount = float_round(amount, 2)
        values.setdefault('amount', amount)

        # currency id
        currency_id = values.setdefault('currency_id', currency_id)
        if currency_id:
            currency = self.env['res.currency'].browse(currency_id)
        else:
            currency = self.env.user.company_id.currency_id
        values['currency'] = currency

        # Fill partner_* using values['partner_id'] or partner_id argument
        partner_id = values.get('partner_id', partner_id)
        billing_partner_id = values.get('billing_partner_id', partner_id)
        if partner_id:
            partner = self.env['res.partner'].browse(partner_id)
            if partner_id != billing_partner_id:
                billing_partner = self.env['res.partner'].browse(
                    billing_partner_id)
            else:
                billing_partner = partner
            values.update({
                'partner':
                partner,
                'partner_id':
                partner_id,
                'partner_name':
                partner.name,
                'partner_lang':
                partner.lang,
                'partner_email':
                partner.email,
                'partner_zip':
                partner.zip,
                'partner_city':
                partner.city,
                'partner_address':
                _partner_format_address(partner.street, partner.street2),
                'partner_country_id':
                partner.country_id.id,
                'partner_country':
                partner.country_id,
                'partner_phone':
                partner.phone,
                'partner_state':
                partner.state_id,
                'billing_partner':
                billing_partner,
                'billing_partner_id':
                billing_partner_id,
                'billing_partner_name':
                billing_partner.name,
                'billing_partner_commercial_company_name':
                billing_partner.commercial_company_name,
                'billing_partner_lang':
                billing_partner.lang,
                'billing_partner_email':
                billing_partner.email,
                'billing_partner_zip':
                billing_partner.zip,
                'billing_partner_city':
                billing_partner.city,
                'billing_partner_address':
                _partner_format_address(billing_partner.street,
                                        billing_partner.street2),
                'billing_partner_country_id':
                billing_partner.country_id.id,
                'billing_partner_country':
                billing_partner.country_id,
                'billing_partner_phone':
                billing_partner.phone,
                'billing_partner_state':
                billing_partner.state_id,
            })
        if values.get('partner_name'):
            values.update({
                'partner_first_name':
                _partner_split_name(values.get('partner_name'))[0],
                'partner_last_name':
                _partner_split_name(values.get('partner_name'))[1],
            })
        if values.get('billing_partner_name'):
            values.update({
                'billing_partner_first_name':
                _partner_split_name(values.get('billing_partner_name'))[0],
                'billing_partner_last_name':
                _partner_split_name(values.get('billing_partner_name'))[1],
            })

        # Fix address, country fields
        if not values.get('partner_address'):
            values['address'] = _partner_format_address(
                values.get('partner_street', ''),
                values.get('partner_street2', ''))
        if not values.get('partner_country') and values.get(
                'partner_country_id'):
            values['country'] = self.env['res.country'].browse(
                values.get('partner_country_id'))
        if not values.get('billing_partner_address'):
            values['billing_address'] = _partner_format_address(
                values.get('billing_partner_street', ''),
                values.get('billing_partner_street2', ''))
        if not values.get('billing_partner_country') and values.get(
                'billing_partner_country_id'):
            values['billing_country'] = self.env['res.country'].browse(
                values.get('billing_partner_country_id'))

        # compute fees
        fees_method_name = '%s_compute_fees' % self.provider
        if hasattr(self, fees_method_name):
            fees = getattr(self,
                           fees_method_name)(values['amount'],
                                             values['currency_id'],
                                             values.get('partner_country_id'))
            values['fees'] = float_round(fees, 2)

        # call <name>_form_generate_values to update the tx dict with acqurier specific values
        cust_method_name = '%s_form_generate_values' % (self.provider)
        if hasattr(self, cust_method_name):
            method = getattr(self, cust_method_name)
            values = method(values)

        values.update({
            'tx_url':
            self._context.get('tx_url', self.get_form_action_url()),
            'submit_class':
            self._context.get('submit_class', 'btn btn-link'),
            'submit_txt':
            self._context.get('submit_txt'),
            'acquirer':
            self,
            'user':
            self.env.user,
            'context':
            self._context,
            'type':
            values.get('type') or 'form',
        })
        values.setdefault('return_url', False)

        return self.view_template_id.render(values, engine='ir.qweb')