Example #1
0
    def _get_invoiced(self):
        # fix de esta funcion porque odoo no lo quiso arreglar
        # cambiamos != purchase por not in purchase, done
        precision = self.env['decimal.precision'].precision_get(
            'Product Unit of Measure')
        for order in self:
            # if order.state != 'purchase':
            if order.state not in ('purchase', 'done'):
                order.invoice_status = 'no'
                continue

            if any(
                    float_compare(line.qty_invoiced,
                                  line.product_qty,
                                  precision_digits=precision) == -1
                    for line in order.order_line):
                order.invoice_status = 'to invoice'
            elif all(
                    float_compare(line.qty_invoiced,
                                  line.product_qty,
                                  precision_digits=precision) >= 0
                    for line in order.order_line):
                order.invoice_status = 'invoiced'
            else:
                order.invoice_status = 'no'
Example #2
0
    def _get_received(self):
        precision = self.env['decimal.precision'].precision_get(
            'Product Unit of Measure')
        for line in self:
            # on v9 odoo consider done with no more to purchase, PR has been
            # deny, if we change it here we should change odoo behaviour on
            # purchase orders
            # al final dejamos  nuestro criterio porque es confuso para
            # clientes y de hecho odoo, a diferencia de lo que dice el boton
            # si te deja crear las facturas en done
            # if line.state != 'purchase':
            if line.state not in ('purchase', 'done'):
                line.delivery_status = 'no'
                continue

            if float_compare(line.qty_received,
                             line.product_qty,
                             precision_digits=precision) == -1:
                line.delivery_status = 'to receive'
            elif float_compare(line.qty_received,
                               line.product_qty,
                               precision_digits=precision) >= 0:
                line.delivery_status = 'received'
            else:
                line.delivery_status = 'no'
Example #3
0
    def _get_delivered(self):
        precision = self.env['decimal.precision'].precision_get(
            'Product Unit of Measure')
        for order in self:
            if order.state not in ('sale', 'done'):
                order.delivery_status = 'no'
                continue

            if order.manually_set_delivered:
                order.delivery_status = 'delivered'
                continue

            if any(
                    float_compare(line.all_qty_delivered,
                                  line.product_uom_qty,
                                  precision_digits=precision) == -1
                    for line in order.order_line):
                order.delivery_status = 'to deliver'
            elif all(
                    float_compare(line.all_qty_delivered,
                                  line.product_uom_qty,
                                  precision_digits=precision) >= 0
                    for line in order.order_line):
                order.delivery_status = 'delivered'
            else:
                order.delivery_status = 'no'
Example #4
0
    def _paypal_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []
        _logger.info('Received a notification from Paypal with IPN version %s', data.get('notify_version'))
        if data.get('test_ipn'):
            _logger.warning(
                'Received a notification from Paypal using sandbox'
            ),

        # TODO: txn_id: shoudl be false at draft, set afterwards, and verified with txn details
        if tx.acquirer_reference and data.get('txn_id') != tx.acquirer_reference:
            invalid_parameters.append(('txn_id', data.get('txn_id'), tx.acquirer_reference))
        # check what is buyed
        if float_compare(float(data.get('mc_gross', '0.0')), (tx.amount + tx.fees), 2) != 0:
            invalid_parameters.append(('mc_gross', data.get('mc_gross'), '%.2f' % tx.amount))  # mc_gross is amount + fees
        if data.get('mc_currency') != tx.currency_id.name:
            invalid_parameters.append(('mc_currency', data.get('mc_currency'), tx.currency_id.name))
        if 'handling_amount' in data and float_compare(float(data.get('handling_amount')), tx.fees, 2) != 0:
            invalid_parameters.append(('handling_amount', data.get('handling_amount'), tx.fees))
        # check buyer
        if tx.partner_reference and data.get('payer_id') != tx.partner_reference:
            invalid_parameters.append(('payer_id', data.get('payer_id'), tx.partner_reference))
        # check seller
        if data.get('receiver_id') and tx.acquirer_id.paypal_seller_account and data['receiver_id'] != tx.acquirer_id.paypal_seller_account:
            invalid_parameters.append(('receiver_id', data.get('receiver_id'), tx.acquirer_id.paypal_seller_account))
        if not data.get('receiver_id') or not tx.acquirer_id.paypal_seller_account:
            # Check receiver_email only if receiver_id was not checked.
            # In Paypal, this is possible to configure as receiver_email a different email than the business email (the login email)
            # In Odoo, there is only one field for the Paypal email: the business email. This isn't possible to set a receiver_email
            # different than the business email. Therefore, if you want such a configuration in your Paypal, you are then obliged to fill
            # the Merchant ID in the Paypal payment acquirer in Odoo, so the check is performed on this variable instead of the receiver_email.
            # At least one of the two checks must be done, to avoid fraudsters.
            if data.get('receiver_email') != tx.acquirer_id.paypal_email_account:
                invalid_parameters.append(('receiver_email', data.get('receiver_email'), tx.acquirer_id.paypal_email_account))

        return invalid_parameters
Example #5
0
 def action_accept_ready_qty(self):
     self.with_incidences = False
     new_moves = []
     for move in self.move_lines:
         if move.state in ('done', 'cancel'):
             # ignore stock moves cancelled or already done
             continue
         precision = move.product_uom.rounding
         remaining_qty = move.product_uom_qty - move.qty_ready
         remaining_qty = float_round(remaining_qty,
                                     precision_rounding=precision)
         if float_compare(remaining_qty, 0,
                          precision_rounding=precision) > 0 and \
             float_compare(remaining_qty, move.product_qty,
                           precision_rounding=precision) < 0:
             new_move = move.split(move, remaining_qty)
             new_moves.append(new_move)
     if new_moves:
         new_moves = self.env['stock.move'].browse(new_moves)
         self._create_backorder(self, backorder_moves=new_moves)
         new_moves.write({'qty_ready': 0.0})
         self.do_unreserve()
         self.recheck_availability()
     self.message_post(body=_("User %s accepted ready quantities.") %
                       (self.env.user.name))
Example #6
0
    def _compute_delivery_status(self):
        precision = self.env['decimal.precision'].precision_get(
            'Product Unit of Measure')
        for line in self:
            if line.state not in ('sale', 'done'):
                line.delivery_status = 'no'
                continue

            if line.order_id.manually_set_delivered:
                line.order_id.delivery_status = 'delivered'
                continue

            if float_compare(
                    line.all_qty_delivered,
                    line.product_uom_qty,
                    # line.qty_delivered, line.product_uom_qty,
                    precision_digits=precision) == -1:
                line.delivery_status = 'to deliver'
            elif float_compare(
                    line.all_qty_delivered,
                    line.product_uom_qty,
                    # line.qty_delivered, line.product_uom_qty,
                    precision_digits=precision) >= 0:
                line.delivery_status = 'delivered'
            else:
                line.delivery_status = 'no'
Example #7
0
    def _paypal_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []
        if data.get('notify_version')[0] != '3.4':
            _logger.warning(
                'Received a notification from Paypal with version %s instead of 2.6. This could lead to issues when managing it.' %
                data.get('notify_version')
            )
        if data.get('test_ipn'):
            _logger.warning(
                'Received a notification from Paypal using sandbox'
            ),

        # TODO: txn_id: shoudl be false at draft, set afterwards, and verified with txn details
        if tx.acquirer_reference and data.get('txn_id') != tx.acquirer_reference:
            invalid_parameters.append(('txn_id', data.get('txn_id'), tx.acquirer_reference))
        # check what is buyed
        if float_compare(float(data.get('mc_gross', '0.0')), (tx.amount + tx.fees), 2) != 0:
            invalid_parameters.append(('mc_gross', data.get('mc_gross'), '%.2f' % tx.amount))  # mc_gross is amount + fees
        if data.get('mc_currency') != tx.currency_id.name:
            invalid_parameters.append(('mc_currency', data.get('mc_currency'), tx.currency_id.name))
        if 'handling_amount' in data and float_compare(float(data.get('handling_amount')), tx.fees, 2) != 0:
            invalid_parameters.append(('handling_amount', data.get('handling_amount'), tx.fees))
        # check buyer
        if tx.partner_reference and data.get('payer_id') != tx.partner_reference:
            invalid_parameters.append(('payer_id', data.get('payer_id'), tx.partner_reference))
        # check seller
        if data.get('receiver_email') != tx.acquirer_id.paypal_email_account:
            invalid_parameters.append(('receiver_email', data.get('receiver_email'), tx.acquirer_id.paypal_email_account))
        if tx.acquirer_id.paypal_seller_account and data.get('receiver_id') != tx.acquirer_id.paypal_seller_account:
            invalid_parameters.append(('receiver_id', data.get('receiver_id'), tx.acquirer_id.paypal_seller_account))

        return invalid_parameters
Example #8
0
    def _paypal_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []
        if data.get('notify_version')[0] != '3.4':
            _logger.warning(
                'Received a notification from Paypal with version %s instead of 2.6. This could lead to issues when managing it.' %
                data.get('notify_version')
            )
        if data.get('test_ipn'):
            _logger.warning(
                'Received a notification from Paypal using sandbox'
            ),

        # TODO: txn_id: shoudl be false at draft, set afterwards, and verified with txn details
        if tx.acquirer_reference and data.get('txn_id') != tx.acquirer_reference:
            invalid_parameters.append(('txn_id', data.get('txn_id'), tx.acquirer_reference))
        # check what is buyed
        if float_compare(float(data.get('mc_gross', '0.0')), (tx.amount + tx.fees), 2) != 0:
            invalid_parameters.append(('mc_gross', data.get('mc_gross'), '%.2f' % tx.amount))  # mc_gross is amount + fees
        if data.get('mc_currency') != tx.currency_id.name:
            invalid_parameters.append(('mc_currency', data.get('mc_currency'), tx.currency_id.name))
        if 'handling_amount' in data and float_compare(float(data.get('handling_amount')), tx.fees, 2) != 0:
            invalid_parameters.append(('handling_amount', data.get('handling_amount'), tx.fees))
        # check buyer
        if tx.partner_reference and data.get('payer_id') != tx.partner_reference:
            invalid_parameters.append(('payer_id', data.get('payer_id'), tx.partner_reference))
        # check seller
        if data.get('receiver_email') != tx.acquirer_id.paypal_email_account:
            invalid_parameters.append(('receiver_email', data.get('receiver_email'), tx.acquirer_id.paypal_email_account))
        if tx.acquirer_id.paypal_seller_account and data.get('receiver_id') != tx.acquirer_id.paypal_seller_account:
            invalid_parameters.append(('receiver_id', data.get('receiver_id'), tx.acquirer_id.paypal_seller_account))

        return invalid_parameters
    def do_partial(self, cr, uid, ids, context=None):
        assert len(ids) == 1, 'Partial picking processing may only be done one at a time.'
        stock_picking = self.pool.get('stock.picking')
        stock_move = self.pool.get('stock.move')
        uom_obj = self.pool.get('product.uom')
        partial = self.browse(cr, uid, ids[0], context=context)
        partial_data = {
            'delivery_date' : partial.date
        }
        picking_type = partial.picking_id.type
        for wizard_line in partial.move_ids:
            line_uom = wizard_line.product_uom
            move_id = wizard_line.move_id.id

            #Quantiny must be Positive
            if wizard_line.quantity < 0:
                raise osv.except_osv(_('Warning!'), _('Please provide proper Quantity.'))

            #Compute the quantity for respective wizard_line in the line uom (this jsut do the rounding if necessary)
            qty_in_line_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.quantity, line_uom.id)

            if line_uom.factor and line_uom.factor <> 0:
                if float_compare(qty_in_line_uom, wizard_line.quantity, precision_rounding=line_uom.rounding) != 0:
                    raise osv.except_osv(_('Warning!'), _('The unit of measure rounding does not allow you to ship "%s %s", only roundings of "%s %s" is accepted by the Unit of Measure.') % (wizard_line.quantity, line_uom.name, line_uom.rounding, line_uom.name))
            if move_id:
                #Check rounding Quantity.ex.
                #picking: 1kg, uom kg rounding = 0.01 (rounding to 10g),
                #partial delivery: 253g
                #=> result= refused, as the qty left on picking would be 0.747kg and only 0.75 is accepted by the uom.
                initial_uom = wizard_line.move_id.product_uom
                #Compute the quantity for respective wizard_line in the initial uom
                qty_in_initial_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.quantity, initial_uom.id)
                without_rounding_qty = (wizard_line.quantity / line_uom.factor) * initial_uom.factor
                if float_compare(qty_in_initial_uom, without_rounding_qty, precision_rounding=initial_uom.rounding) != 0:
                    raise osv.except_osv(_('Warning!'), _('The rounding of the initial uom does not allow you to ship "%s %s", as it would let a quantity of "%s %s" to ship and only roundings of "%s %s" is accepted by the uom.') % (wizard_line.quantity, line_uom.name, wizard_line.move_id.product_qty - without_rounding_qty, initial_uom.name, initial_uom.rounding, initial_uom.name))
            else:
                seq_obj_name =  'stock.picking.' + picking_type
                move_id = stock_move.create(cr,uid,{'name' : self.pool.get('ir.sequence').get(cr, uid, seq_obj_name),
                                                    'product_id': wizard_line.product_id.id,
                                                    'product_qty': wizard_line.quantity,
                                                    'product_uom': wizard_line.product_uom.id,
                                                    'prodlot_id': wizard_line.prodlot_id.id,
                                                    'location_id' : wizard_line.location_id.id,
                                                    'location_dest_id' : wizard_line.location_dest_id.id,
                                                    'picking_id': partial.picking_id.id,
                                                    'employee_id':wizard_line.employee_id.id,
                                                    },context=context)
                stock_move.action_confirm(cr, uid, [move_id], context)
            partial_data['move%s' % (move_id)] = {
                'product_id': wizard_line.product_id.id,
                'product_qty': wizard_line.quantity,
                'product_uom': wizard_line.product_uom.id,
                'prodlot_id': wizard_line.prodlot_id.id,
                'employee_id':wizard_line.employee_id.id,
            }
            if (picking_type == 'in') and (wizard_line.product_id.cost_method == 'average'):
                partial_data['move%s' % (wizard_line.move_id.id)].update(product_price=wizard_line.cost,
                                                                  product_currency=wizard_line.currency.id)
        stock_picking.do_partial(cr, uid, [partial.picking_id.id], partial_data, context=context)
        return {'type': 'ir.actions.act_window_close'}
    def interval_min_get(self, cr, uid, id, dt_from, hours, resource=False):
        """
        Calculates the working Schedule from supplied from date to till hours
        will be satisfied  based or resource calendar id. If resource is also
        given then it will consider the resource leave also and than will
        calculates resource working schedule

        @param dt_from: datetime object, start of working scheduled
        @param hours: float, total number working  hours needed scheduled from
                      start date
        @param resource : Optional Resource id, if supplied than resource leaves
                        will also taken into consideration for calculating working
                        schedule.
        @return : List datetime object of working schedule based on supplies
                  params
        """
        if not id:
            td = int(hours) * 3
            return [(dt_from - timedelta(hours=td), dt_from)]
        dt_leave = self._get_leaves(cr, uid, id, resource)
        dt_leave.reverse()
        todo = hours
        result = []
        maxrecur = 100
        current_hour = dt_from.hour
        while float_compare(todo, 0, 4) and maxrecur:
            cr.execute(
                "select hour_from,hour_to from resource_calendar_attendance where dayofweek='%s' and calendar_id=%s order by hour_from desc",
                (dt_from.weekday(), id),
            )
            for (hour_from, hour_to) in cr.fetchall():
                leave_flag = False
                if (hour_from < current_hour) and float_compare(todo, 0, 4):
                    m = min(hour_to, current_hour)
                    if (m - hour_from) > todo:
                        hour_from = m - todo
                    dt_check = dt_from.strftime("%Y-%m-%d")
                    for leave in dt_leave:
                        if dt_check == leave:
                            dt_check = datetime.strptime(dt_check, "%Y-%m-%d") + timedelta(days=1)
                            leave_flag = True
                    if leave_flag:
                        break
                    else:
                        d1 = datetime(
                            dt_from.year,
                            dt_from.month,
                            dt_from.day,
                            int(math.floor(hour_from)),
                            int((hour_from % 1) * 60),
                        )
                        d2 = datetime(dt_from.year, dt_from.month, dt_from.day, int(math.floor(m)), int((m % 1) * 60))
                        result.append((d1, d2))
                        current_hour = hour_from
                        todo -= m - hour_from
            dt_from -= timedelta(days=1)
            current_hour = 24
            maxrecur -= 1
        result.reverse()
        return result
Example #11
0
 def action_accept_ready_qty(self):
     self.with_incidences = False
     new_moves = []
     for move in self.move_lines:
         if move.state in ('done', 'cancel'):
             # ignore stock moves cancelled or already done
             continue
         precision = move.product_uom.rounding
         remaining_qty = move.product_uom_qty - move.qty_ready
         remaining_qty = float_round(remaining_qty,
                                     precision_rounding=precision)
         if not move.qty_ready:
             new_moves.append(move.id)
         elif float_compare(remaining_qty, 0,
                            precision_rounding=precision) > 0 and \
             float_compare(remaining_qty, move.product_qty,
                           precision_rounding=precision) < 0:
             new_move = move.split(move, remaining_qty)
             new_moves.append(new_move)
     if new_moves:
         new_moves = self.env['stock.move'].browse(new_moves)
         bcko_id = self._create_backorder(self, backorder_moves=new_moves)
         bck = self.browse(bcko_id)
         new_moves.write({'qty_ready': 0.0})
         self.do_unreserve()
         self.recheck_availability()
     self.message_post(body=_("User %s accepted ready quantities.") %
                       (self.env.user.name))
     self.action_done()
     self.date_done = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
Example #12
0
    def _paypal_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []
        _logger.info('Received a notification from Paypal with IPN version %s', data.get('notify_version'))
        if data.get('test_ipn'):
            _logger.warning(
                'Received a notification from Paypal using sandbox'
            ),

        # TODO: txn_id: shoudl be false at draft, set afterwards, and verified with txn details
        if tx.acquirer_reference and data.get('txn_id') != tx.acquirer_reference:
            invalid_parameters.append(('txn_id', data.get('txn_id'), tx.acquirer_reference))
        # check what is buyed
        if float_compare(float(data.get('mc_gross', '0.0')), (tx.amount + tx.fees), 2) != 0:
            invalid_parameters.append(('mc_gross', data.get('mc_gross'), '%.2f' % tx.amount))  # mc_gross is amount + fees
        if data.get('mc_currency') != tx.currency_id.name:
            invalid_parameters.append(('mc_currency', data.get('mc_currency'), tx.currency_id.name))
        if 'handling_amount' in data and float_compare(float(data.get('handling_amount')), tx.fees, 2) != 0:
            invalid_parameters.append(('handling_amount', data.get('handling_amount'), tx.fees))
        # check buyer
        if tx.payment_method_id and data.get('payer_id') != tx.payment_method_id.acquirer_ref:
            invalid_parameters.append(('payer_id', data.get('payer_id'), tx.payment_method_id.acquirer_ref))
        # check seller
        if data.get('receiver_id') and tx.acquirer_id.paypal_seller_account and data['receiver_id'] != tx.acquirer_id.paypal_seller_account:
            invalid_parameters.append(('receiver_id', data.get('receiver_id'), tx.acquirer_id.paypal_seller_account))
        if not data.get('receiver_id') or not tx.acquirer_id.paypal_seller_account:
            # Check receiver_email only if receiver_id was not checked.
            # In Paypal, this is possible to configure as receiver_email a different email than the business email (the login email)
            # In Odoo, there is only one field for the Paypal email: the business email. This isn't possible to set a receiver_email
            # different than the business email. Therefore, if you want such a configuration in your Paypal, you are then obliged to fill
            # the Merchant ID in the Paypal payment acquirer in Odoo, so the check is performed on this variable instead of the receiver_email.
            # At least one of the two checks must be done, to avoid fraudsters.
            if data.get('receiver_email') != tx.acquirer_id.paypal_email_account:
                invalid_parameters.append(('receiver_email', data.get('receiver_email'), tx.acquirer_id.paypal_email_account))

        return invalid_parameters
Example #13
0
 def _do_partial(self, cr, uid, ids, context=None):
     assert len(ids) == 1, 'Partial picking processing may only be done one at a time.'
     stock_picking = self.pool.get('stock.picking')
     stock_move = self.pool.get('stock.move')
     uom_obj = self.pool.get('product.uom')
     partial = self.browse(cr, uid, ids[0], context=context)
     partial_data = {
         'delivery_date' : partial.date
     }
     picking_type = partial.picking_id.type
     
     for wizard_line in partial.move_ids:
         line_uom = wizard_line.product_uom
         move_id = wizard_line.move_id.id
     #Quantiny must be Positive
         if wizard_line.quantity < 0:
             raise osv.except_osv(_('Warning!'), _('Please provide proper Quantity.'))
 
         #Compute the quantity for respective wizard_line in the line uom (this jsut do the rounding if necessary)
         qty_in_line_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.quantity, line_uom.id)
 
         if line_uom.factor and line_uom.factor <> 0:
             if float_compare(qty_in_line_uom, wizard_line.quantity, precision_rounding=line_uom.rounding) != 0:
                 raise osv.except_osv(_('Warning!'), _('The unit of measure rounding does not allow you to ship "%s %s", only rounding of "%s %s" is accepted by the Unit of Measure.') % (wizard_line.quantity, line_uom.name, line_uom.rounding, line_uom.name))
         if move_id:
             #Check rounding Quantity.ex.
             #picking: 1kg, uom kg rounding = 0.01 (rounding to 10g),
             #partial delivery: 253g
             #=> result= refused, as the qty left on picking would be 0.747kg and only 0.75 is accepted by the uom.
             initial_uom = wizard_line.move_id.product_uom
             #Compute the quantity for respective wizard_line in the initial uom
             qty_in_initial_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.quantity, initial_uom.id)
             without_rounding_qty = (wizard_line.quantity / line_uom.factor) * initial_uom.factor
             if float_compare(qty_in_initial_uom, without_rounding_qty, precision_rounding=initial_uom.rounding) != 0:
                 raise osv.except_osv(_('Warning!'), _('The rounding of the initial uom does not allow you to ship "%s %s", as it would let a quantity of "%s %s" to ship and only rounding of "%s %s" is accepted by the uom.') % (wizard_line.quantity, line_uom.name, wizard_line.move_id.product_qty - without_rounding_qty, initial_uom.name, initial_uom.rounding, initial_uom.name))
         else:
             seq_obj_name =  'stock.picking.' + picking_type
             move_id = stock_move.create(cr,uid,{'name' : self.pool.get('ir.sequence').get(cr, uid, seq_obj_name),
                                                 'product_id': wizard_line.product_id.id,
                                                 'product_qty': wizard_line.quantity,
                                                 'product_uom': wizard_line.product_uom.id,
                                                 'prodlot_id': wizard_line.prodlot_id.id,
                                                 'location_id' : wizard_line.location_id.id,
                                                 'location_dest_id' : wizard_line.location_dest_id.id,
                                                 'picking_id': partial.picking_id.id
                                                 },context=context)
             stock_move.action_confirm(cr, uid, [move_id], context)
         partial_data['move%s' % (move_id)] = {
             'product_id': wizard_line.product_id.id,
             'product_qty': wizard_line.quantity,
             'product_uom': wizard_line.product_uom.id,
             'prodlot_id': wizard_line.prodlot_id.id,
         }
         if (picking_type == 'in') and (wizard_line.product_id.cost_method == 'average'):
             partial_data['move%s' % (wizard_line.move_id.id)].update(product_price=wizard_line.cost,
                                                               product_currency=wizard_line.currency.id)
     # print "****PARTIAL_DATA********: ", partial_data
     stock_picking.do_partial(cr, uid, [partial.picking_id.id], partial_data, context=context)
     return {'type': 'ir.actions.act_window_close'}
Example #14
0
    def quants_reserve(self, cr, uid, quants, move, link=False, context=None):
        '''This function reserves quants for the given move (and optionally given link). If the total of quantity reserved is enough, the move's state
        is also set to 'assigned'

        :param quants: list of tuple(quant browse record or None, qty to reserve). If None is given as first tuple element, the item will be ignored. Negative quants should not be received as argument
        :param move: browse record
        :param link: browse record (stock.move.operation.link)
        '''
        toreserve = []
        reserved_availability = move.reserved_availability
        #split quants if needed
        for quant, qty in quants:
            if qty <= 0.0 or (quant and quant.qty <= 0.0):
                raise osv.except_osv(
                    _('Error!'),
                    _('You can not reserve a negative quantity or a negative quant.'
                      ))
            if not quant:
                continue
            self._quant_split(cr, uid, quant, qty, context=context)
            toreserve.append(quant.id)
            reserved_availability += quant.qty
        #reserve quants
        if toreserve:
            self.write(
                cr,
                SUPERUSER_ID,
                toreserve, {
                    'reservation_id':
                    move.id,
                    'in_date':
                    datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
                },
                context=context)
            #if move has a picking_id, write on that picking that pack_operation might have changed and need to be recomputed
            if move.picking_id:
                self.pool.get('stock.picking').write(
                    cr,
                    uid, [move.picking_id.id], {'recompute_pack_op': True},
                    context=context)
        #check if move'state needs to be set as 'assigned'
        rounding = move.product_id.uom_id.rounding
        if float_compare(reserved_availability,
                         move.product_qty,
                         precision_rounding=rounding) == 0 and move.state in (
                             'confirmed', 'waiting'):
            self.pool.get('stock.move').write(cr,
                                              uid, [move.id],
                                              {'state': 'assigned'},
                                              context=context)
        elif float_compare(
                reserved_availability, 0, precision_rounding=rounding
        ) > 0 and not move.partially_available:
            self.pool.get('stock.move').write(cr,
                                              uid, [move.id],
                                              {'partially_available': True},
                                              context=context)
Example #15
0
    def interval_min_get(self, cr, uid, id, dt_from, hours, resource=False):
        """
        Calculates the working Schedule from supplied from date to till hours
        will be satisfied  based or resource calendar id. If resource is also
        given then it will consider the resource leave also and than will
        calculates resource working schedule

        @param dt_from: datetime object, start of working scheduled
        @param hours: float, total number working  hours needed scheduled from
                      start date
        @param resource : Optional Resource id, if supplied than resource leaves
                        will also taken into consideration for calculating working
                        schedule.
        @return : List datetime object of working schedule based on supplies
                  params
        """
        if not id:
            td = int(hours) * 3
            return [(dt_from - timedelta(hours=td), dt_from)]
        dt_leave = self._get_leaves(cr, uid, id, resource)
        dt_leave.reverse()
        todo = hours
        result = []
        maxrecur = 100
        current_hour = dt_from.hour
        while float_compare(todo, 0, 4) and maxrecur:
            cr.execute(
                "select hour_from,hour_to from resource_calendar_attendance where dayofweek='%s' and calendar_id=%s order by hour_from desc",
                (dt_from.weekday(), id))
            for (hour_from, hour_to) in cr.fetchall():
                leave_flag = False
                if (hour_from < current_hour) and float_compare(todo, 0, 4):
                    m = min(hour_to, current_hour)
                    if (m - hour_from) > todo:
                        hour_from = m - todo
                    dt_check = dt_from.strftime('%Y-%m-%d')
                    for leave in dt_leave:
                        if dt_check == leave:
                            dt_check = datetime.strptime(
                                dt_check, '%Y-%m-%d') + timedelta(days=1)
                            leave_flag = True
                    if leave_flag:
                        break
                    else:
                        d1 = datetime(dt_from.year, dt_from.month, dt_from.day,
                                      int(math.floor(hour_from)),
                                      int((hour_from % 1) * 60))
                        d2 = datetime(dt_from.year, dt_from.month, dt_from.day,
                                      int(math.floor(m)), int((m % 1) * 60))
                        result.append((d1, d2))
                        current_hour = hour_from
                        todo -= (m - hour_from)
            dt_from -= timedelta(days=1)
            current_hour = 24
            maxrecur -= 1
        result.reverse()
        return result
Example #16
0
    def get_quants_line(self, forced_quants_list=False):
        """
        Check if required quantity is available in source location,
        No multiproduct packs when we are inside this method
        """
        t_quant = self.env['stock.quant']
        res = []
        line = self[0]  # Is called always line by line
        if forced_quants_list:
            for quant in forced_quants_list:
                res.append((quant, quant.qty))
        else:
            if line.product_id:  # Move products from a pack or alone
                line_qty = line.quantity
                product = line.product_id
            else:  # Move entire packs
                line_qty = line.package_id.packed_qty  # No multiproduct pack
                product = line.package_id.product_id  # No multiproduct pack

            # Search quants to force the assignament later
            domain = [('product_id', '=', product.id),
                      ('location_id', '=', line.src_location_id.id),
                      ('package_id', '=', line.package_id.id),
                      ('qty', '>', 0.0)]
            if line.lot_id:
                domain.append(('lot_id', '=', line.lot_id.id))
            quants_objs = t_quant.search(domain)
            assigned_qty = 0
            rst_qty = line_qty
            for quant in quants_objs:
                if float_compare(
                        assigned_qty,
                        line_qty,
                        precision_rounding=product.uom_id.rounding) == -1:
                    #if assigned_qty < line_qty:
                    if float_compare(
                            rst_qty,
                            quant.qty,
                            precision_rounding=product.uom_id.rounding) != -1:
                        #if rst_qty >= quant.qty:
                        res.append((quant, quant.qty))
                        assigned_qty += quant.qty
                    else:
                        res.append((quant, rst_qty))
                        assigned_qty += rst_qty
                    rst_qty = line_qty - assigned_qty

            if float_compare(assigned_qty,
                             line_qty,
                             precision_rounding=product.uom_id.rounding) == -1:
                #if assigned_qty < line_qty:
                raise except_orm(
                    _('Error'),
                    _('Not enought stock available\
                                 for product %s, and quantity of \
                                 %s units' % (product.name, line_qty)))
        return res
Example #17
0
	def do_transfer(self, cr, uid, picking_ids, context=None):
		"""
			If no pack operation, we do simple action_done of the picking
			Otherwise, do the pack operations
		"""
		if not context:
			context = {}
		notrack_context = dict(context, mail_notrack=True)
		stock_move_obj = self.pool.get('stock.move')
		for picking in self.browse(cr, uid, picking_ids, context=context):
			if not picking.pack_operation_ids:
				self.action_done(cr, uid, [picking.id], context=context)
				continue
			else:
				need_rereserve, all_op_processed = self.picking_recompute_remaining_quantities(cr, uid, picking, context=context)
				#create extra moves in the picking (unexpected product moves coming from pack operations)
				todo_move_ids = []
				if not all_op_processed:
					todo_move_ids += self._create_extra_moves(cr, uid, picking, context=context)

				#split move lines if needed
				toassign_move_ids = []
				for move in picking.move_lines:
					remaining_qty = move.remaining_qty
					if move.state in ('done', 'cancel'):
						#ignore stock moves cancelled or already done
						continue
					elif move.state == 'draft':
						toassign_move_ids.append(move.id)
					if float_compare(remaining_qty, 0,  precision_rounding = move.product_id.uom_id.rounding) == 0:
						if move.state in ('draft', 'assigned', 'confirmed'):
							todo_move_ids.append(move.id)
					elif float_compare(remaining_qty,0, precision_rounding = move.product_id.uom_id.rounding) > 0 and \
								float_compare(remaining_qty, move.product_qty, precision_rounding = move.product_id.uom_id.rounding) < 0:
						new_move = stock_move_obj.split(cr, uid, move, remaining_qty, context=notrack_context)
						todo_move_ids.append(move.id)
						#Assign move as it was assigned before
						toassign_move_ids.append(new_move)
				if need_rereserve or not all_op_processed: 
					if not picking.location_id.usage in ("supplier", "production", "inventory"):
						self.rereserve_quants(cr, uid, picking, move_ids=todo_move_ids, context=context)
					self.do_recompute_remaining_quantities(cr, uid, [picking.id], context=context)
				if todo_move_ids and not context.get('do_only_split'):
					self.pool.get('stock.move').action_done(cr, uid, todo_move_ids, context=notrack_context)
				elif context.get('do_only_split'):
					context = dict(context, split=todo_move_ids)
			backorder_id = self._create_backorder(cr, uid, picking, context=context)
			if toassign_move_ids:
				stock_move_obj.action_assign(cr, uid, toassign_move_ids, context=context)
			picking_obj = self.pool.get("stock.picking")
			picking_id = picking_obj.browse(cr, uid, backorder_id)

			if picking_id:
				if picking_id.state not in ('done', 'cancel'):
					self.do_unreserve(cr, uid, picking_id.id, context=context)
		return True
Example #18
0
 def get_purchase_line_procurements(self,
                                    first_proc,
                                    seller,
                                    order_by,
                                    force_domain=None):
     """Returns procurements that must be integrated in the same purchase order line as first_proc, by
     taking all procurements of the same product as first_proc between the date of first proc and date_end.
     """
     frame = seller.order_group_period
     date_end = False
     if frame and frame.period_type:
         date_end = fields.Datetime.to_string(
             frame.get_date_end_period(
                 fields.Datetime.from_string(first_proc.date_planned)))
     domain_procurements = [('product_id', '=', first_proc.product_id.id),
                            ('location_id', '=', first_proc.location_id.id),
                            ('company_id', '=', first_proc.company_id.id),
                            ('date_planned', '>=', first_proc.date_planned)
                            ] + (force_domain or [])
     if first_proc.rule_id.picking_type_id:
         domain_procurements += [('rule_id.picking_type_id', '=',
                                  first_proc.rule_id.picking_type_id.id)]
     domain_max_date = date_end and [('date_planned', '<', date_end)] or []
     procurements_grouping_period = self.search(domain_procurements +
                                                domain_max_date,
                                                order=order_by)
     line_qty_product_uom = sum([
         self.env['product.uom']._compute_qty(proc.product_uom.id,
                                              proc.product_qty,
                                              proc.product_id.uom_id.id)
         for proc in procurements_grouping_period
     ])
     suppliers = first_proc.product_id.seller_ids. \
         filtered(lambda supplier: supplier.name == self._get_product_supplier(first_proc))
     moq = suppliers and suppliers[0].min_qty or False
     if moq and float_compare(
             line_qty_product_uom,
             moq,
             precision_rounding=first_proc.product_id.uom_id.rounding) < 0:
         procurements_after_period = self.search(
             domain_procurements +
             [('id', 'not in', procurements_grouping_period.ids)],
             order=order_by)
         for proc in procurements_after_period:
             proc_qty_product_uom = self.env['product.uom']. \
                 _compute_qty(proc.product_uom.id, proc.product_qty,
                              proc.product_id.uom_id.id)
             if float_compare(line_qty_product_uom + proc_qty_product_uom,
                              moq,
                              precision_rounding=proc.product_id.uom_id.
                              rounding) > 0:
                 break
             procurements_grouping_period |= proc
             line_qty_product_uom += proc_qty_product_uom
     return self.search([('id', 'in', procurements_grouping_period.ids)],
                        order=order_by)
    def action_apply_all(self, cr, uid, ids, context=None):
        """
            Ejecuta la entrega de todos los movimientos del pedido
        """
        date = time.strftime('%Y-%m-%d %H:%M:%S')
        rline_obj = self.pool.get('delivery.route.line')
        picking_obj = self.pool.get('stock.picking')
        move_obj = self.pool.get('stock.move')
        uom_obj = self.pool.get('product.uom')
        # Obtiene la informacion del wizard
        data = self.browse(cr, uid, ids[0], context=context)
        partial_data = {
            'delivery_date' : date
        }
        picking_type = data.picking_id.type
        # Recorre las lineas a entregar
        for wizard_line in data.line_ids:
            line_uom = wizard_line.product_uom
            move_id = wizard_line.move_id.id

            # Valida que haya un movimiento relacionado
            if not move_id:
                continue
            # Valida que la cantidad de la linea del pedido no sea negativo
            if wizard_line.product_qty < 0:
                raise osv.except_osv(_('Warning!'), _('No puede hacer entregas de productos sobre cantidades negativas.'))

            # Calcula la cantidad del producto en base a la unidad de medida base
            qty_in_line_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.product_qty, line_uom.id)

            # Valida el factor de la linea
            if line_uom.factor and line_uom.factor != 0:
                if float_compare(qty_in_line_uom, wizard_line.product_qty, precision_rounding=line_uom.rounding) != 0:
                    raise osv.except_osv(_('Warning!'), _('La unidad de redondeo medida no permite que usted envíe "%s %s", solo redondeo de "%s %s" es aceptado por la unidad de medida.') % (wizard_line.product_qty, line_uom.name, line_uom.rounding, line_uom.name))
            # Valida que el movimiento no este entregado
            if wizard_line.move_id.state != 'done':
                initial_uom = wizard_line.move_id.product_uom
                #Compute the quantity for respective wizard_line in the initial uom
                qty_in_initial_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.product_qty, initial_uom.id)
                without_rounding_qty = (wizard_line.product_qty / line_uom.factor) * initial_uom.factor
                if float_compare(qty_in_initial_uom, without_rounding_qty, precision_rounding=initial_uom.rounding) != 0:
                    raise osv.except_osv(_('Warning!'), _('La unidad de redondeo medida no permite que usted envíe "%s %s", solo redondeo de "%s %s" es aceptado por la unidad de medida.') % (wizard_line.product_qty, line_uom.name, line_uom.rounding, line_uom.name))
                # Agrega la informacion del producto a entregar
                partial_data['move%s' % (move_id)] = {
                    'product_id': wizard_line.product_id.id or False,
                    'product_qty': wizard_line.product_qty,
                    'product_uom': wizard_line.product_uom.id or False,
                    'prodlot_id': wizard_line.move_id.prodlot_id.id or False,
                }
        # Aplica la salida de almacen sobre los productos a entregar
        picking_obj.do_partial(cr, uid, [data.picking_id.id], partial_data, context=context)
        # Indica que la linea fue entregada
        rline_obj.write(cr, uid, [data.route_line_id.id], {'delivered': True}, context=context)
        # Pone la linea de la ruta como entregado
        rline_obj.action_done(cr, uid, [data.route_line_id.id], context=context)
        return {'type': 'ir.actions.act_window_close'}
Example #20
0
    def do_partial(self, cr, uid, ids, context=None):
        requestion_lines= []
        request = context.get('request', False)
        wf_service = netsvc.LocalService("workflow")
        if request:
            assert len(ids) == 1, 'request product processing may only be done one at a time.'
            requestion_obj = self.pool.get('purchase.requisition')
            uom_obj = self.pool.get('product.uom')
            partial = self.browse(cr, uid, ids[0], context=context)

            for wizard_line in self.pool.get('stock.picking').browse(cr,uid,[partial.picking_id.id])[0].move_lines:
                line_uom = wizard_line.product_uom
                move_id = wizard_line.id
    
                #Quantiny must be Positive
                if wizard_line.product_qty < 0:
                    raise osv.except_osv(_('Warning!'), _('Please provide proper Quantity.'))
    
                #Compute the quantity for respective wizard_line in the line uom (this jsut do the rounding if necessary)
                qty_in_line_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.product_qty, line_uom.id)
    
                if line_uom.factor and line_uom.factor <> 0:
                    if float_compare(qty_in_line_uom, wizard_line.product_qty, precision_rounding=line_uom.rounding) != 0:
                        raise osv.except_osv(_('Warning!'), _('The unit of measure rounding does not allow you to ship "%s %s", only rounding of "%s %s" is accepted by the Unit of Measure.') % (wizard_line.product_qty, line_uom.name, line_uom.rounding, line_uom.name))
                if move_id:                   
                    initial_uom = wizard_line.product_uom
                    qty_in_initial_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.product_qty, initial_uom.id)
                    without_rounding_qty = (wizard_line.product_qty / line_uom.factor) * initial_uom.factor
                    if float_compare(qty_in_initial_uom, without_rounding_qty, precision_rounding=initial_uom.rounding) != 0:
                        raise osv.except_osv(_('Warning!'), _('The rounding of the initial uom does not allow you to ship "%s %s", as it would let a quantity of "%s %s" to ship and only rounding of "%s %s" is accepted by the uom.') % (wizard_line.product_qty, line_uom.name, wizard_line.product_qty - without_rounding_qty, initial_uom.name, initial_uom.rounding, initial_uom.name))
               
                    
                    line = {'name': wizard_line.name,
                            'product_id': wizard_line.product_id.id,
                            'product_qty': wizard_line.product_qty,
                            'product_uom_id': wizard_line.product_uom.id,
                    } 
                    requestion_lines.append((0, 0, line))
            if requestion_lines:
               if partial.picking_id.purchase_requisition_id:
                  raise osv.except_osv(_('Duplication!'), _('You are Already Created Purchase Requisition Before "%s" ') % (partial.picking_id.purchase_requisition_id.name) ) 
               requestion_id = requestion_obj.create(cr, uid , {
                    
                    'origin': partial.picking_id.name,
                    'department_id': partial.picking_id.department_id.id,
                    'category_id':partial.picking_id.category_id.id,
                    'line_ids': requestion_lines}, context = context)
            
            self.pool.get('stock.picking').write( cr, uid, partial.picking_id.id, {'purchase_requisition_id' : requestion_id})
            wf_service.trg_validate(uid, 'purchase.requisition', requestion_id, 'draft_to_approve', cr)
        else:
            return super(stock_partial_picking, self).do_partial(cr, uid, ids, context=context)

        return {'type': 'ir.actions.act_window_close'}
Example #21
0
    def _check_split_possible(self, done_procs_qty):
        """
        Raises error if it is impossible to split the purchase order line.
        """

        prec = self.line_id.product_uom.rounding

        self.ensure_one()
        if self.env.context.get('active_ids') and len(
                self.env.context.get('active_ids')) > 1:
            raise exceptions.except_orm(_('Error!'),
                                        _("Please split lines one by one"))
        else:
            if float_compare(self.qty, 0, precision_rounding=prec) <= 0:
                raise exceptions.except_orm(
                    _('Error!'),
                    _("Impossible to split a negative or null quantity"))
            if self.line_id.state not in ['draft', 'confirmed']:
                raise exceptions.except_orm(
                    _('Error!'),
                    _("Impossible to split line which is not in state draft or "
                      "confirmed"))
            if self.line_id.state == 'draft':
                if float_compare(self.qty,
                                 self.line_id.product_qty,
                                 precision_rounding=prec) >= 0:
                    raise exceptions.except_orm(
                        _('Error!'),
                        _("Please choose a lower quantity to split"))
        if float_compare(self.qty, done_procs_qty,
                         precision_rounding=prec) < 0:
            raise exceptions.except_orm(
                _('Error!'), _("Please choose a lower quantity to split"))
        if self.line_id.state == 'confirmed':
            _sum = sum([
                x.product_qty for x in self.line_id.move_ids
                if x.state == 'done'
            ])
            _sum_pol_uom = self.env['product.uom']._compute_qty(
                self.line_id.product_id.uom_id.id, _sum,
                self.line_id.product_uom.id)
            if self.qty < _sum_pol_uom:
                raise exceptions.except_orm(
                    _('Error!'), _("Impossible to split a move in state done"))
            not_cancelled_qty = sum([
                m.product_qty for m in self.line_id.move_ids
                if m.state != 'cancel'
            ])
            not_cancelled_qty_pol_uom = self.env['product.uom']._compute_qty(
                self.line_id.product_id.uom_id.id, not_cancelled_qty,
                self.line_id.product_uom.id)
            if self.qty >= not_cancelled_qty_pol_uom:
                raise exceptions.except_orm(
                    _('Error!'), _("Please choose a lower quantity to split"))
Example #22
0
 def _release_fiscal_budget(self, fiscalyear, released_amount):
     """ Distribute budget released to all AG of the same year
         by distribute to the first AG first,
         show warning if released amount > planned amout
     """
     # Not current year, no budget release allowed
     current_fy = self.env['account.fiscalyear'].find()
     release_external_budget = fiscalyear.control_ext_charge_only
     for project in self.sudo():
         if project.current_fy_release_only and current_fy != fiscalyear.id:
             raise ValidationError(
                 _('Not allow to release budget for fiscalyear %s!\nOnly '
                   'current year budget is allowed.' % fiscalyear.name))
         budget_plans = project.budget_plan_ids.filtered(
             lambda l: l.fiscalyear_id == fiscalyear)
         budget_monitor = project.monitor_expense_ids.filtered(
             lambda l: l.fiscalyear_id == fiscalyear and l.budget_method ==
             'expense' and l.charge_type == 'external')
         budget_plans.write({'released_amount': 0.0})  # Set zero
         if release_external_budget:  # Only for external charge
             budget_plans = budget_plans.\
                 filtered(lambda l: l.charge_type == 'external')
         if not budget_plans:
             raise ValidationError(
                 _('Not allow to release budget for project without plan!'))
         planned_amount = sum([x.planned_amount for x in budget_plans])
         consumed_amount = sum([x.amount_consumed for x in budget_monitor])
         if float_compare(released_amount, planned_amount, 2) == 1:
             raise ValidationError(
                 _('Releasing budget (%s) > planned (%s)!' %
                   ('{:,.2f}'.format(released_amount),
                    '{:,.2f}'.format(planned_amount))))
         if float_compare(released_amount, consumed_amount, 2) == -1:
             raise ValidationError(
                 _('Releasing budget (%s) < Consumed Amount (%s)!' %
                   ('{:,.2f}'.format(released_amount),
                    '{:,.2f}'.format(consumed_amount))))
         remaining = released_amount
         update_vals = []
         for budget_plan in budget_plans:
             if float_compare(remaining, budget_plan.planned_amount,
                              2) == 1:
                 update = {'released_amount': budget_plan.planned_amount}
                 remaining -= budget_plan.planned_amount
                 update_vals.append((1, budget_plan.id, update))
             else:
                 update = {'released_amount': remaining}
                 remaining = 0.0
                 update_vals.append((1, budget_plan.id, update))
                 break
         if update_vals:
             project.write({'budget_plan_ids': update_vals})
     return True
Example #23
0
 def _create_negative_clearing_line(self, expense, invoice):
     # Use invoice line first
     advance_expense = expense.advance_expense_id
     if advance_expense.invoice_id.invoice_line:
         amount_advance = expense.amount
         if float_compare(amount_advance,
                          advance_expense.amount_to_clearing, 2) == 1:
             amount_advance = advance_expense.amount_to_clearing
         advance_line = advance_expense.invoice_id.invoice_line[0]
         advance_line.copy({
             'invoice_id': invoice.id,
             'price_unit': -amount_advance,
             'sequence': 1,
         })
     # If no invoice line, use advance line and change it to invoice line
     elif advance_expense.line_ids:
         advance_line = advance_expense.line_ids[0]
         advance_account_id = advance_line._get_non_product_account_id()
         line_dict = advance_line.copy_data()
         for line in line_dict:
             # Remove some key
             keys = [
                 'expense_id', 'inrev_activity_id', 'description', 'ref'
             ]
             for key in keys:
                 del line[key]
             # Change some key
             inv_exp = {
                 'quantity': 'unit_quantity',
                 'account_analytic_id': 'analytic_account',
                 'price_unit': 'unit_amount',
                 'invoice_line_tax_id': 'tax_ids',
             }
             for new_key, old_key in inv_exp.iteritems():
                 line[new_key] = line.pop(old_key)
             # Added fields
             cleared_ids = advance_expense.advance_clearing_ids
             max_clear_amount = advance_expense.amount_advanced - \
                 sum(cleared_ids.mapped('clearing_amount'))
             amount_advance = expense.amount
             if float_compare(amount_advance, max_clear_amount, 2) == 1:
                 amount_advance = max_clear_amount
             line.update({
                 'account_id': advance_account_id,
                 'invoice_id': invoice.id,
                 'price_unit': -amount_advance,
                 'sequence': 1,
             })
             self.env['account.invoice.line'].create(line)
     else:
         raise ValidationError(_('No advance product line to reference'))
     return True
Example #24
0
    def testReopen(self):
        """Test re-opening a petty cash fund"""

        # Create a fund and close it
        #
        pcf1 = self.create_fund('Petty Cash Fund 01')
        self.assertEqual(pcf1.state, 'open')

        # Run the close wizard
        Wizard = self.env['account.pettycash.fund.close']
        ctx = self.env.context.copy()
        ctx.update({'active_id': pcf1.id})
        wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({
            'receivable_account': self.receivable_account.id,
            'effective_date': datetime.today().date(),
        })
        self.assertEqual(wiz.fund.id, pcf1.id)
        wiz.sudo(self.uidFinMgr).close_fund()
        self.assertEqual(pcf1.state, 'closed')
        self.assertFalse(pcf1.active)

        # Re-open the fund
        Wizard = self.env['account.pettycash.fund.reopen']
        ctx = self.env.context.copy()
        ctx.update({'active_id': pcf1.id})
        wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({
            'payable_account': self.payable_account.id,
            'effective_date': datetime.today().date(),
        })
        wiz.sudo(self.uidFinMgr).reopen_fund()

        self.assertEqual(pcf1.state, 'open')
        self.assertTrue(pcf1.active)

        self.assertEqual(wiz.payable_move.state, 'posted')

        # Check ledger accounts have been updated properly:
        # Accounts payable should have a credit for the fund amount.
        # The fund account should have a debit for same amount.
        move = wiz.payable_move
        ml1 = move.line_id[0]
        ml2 = move.line_id[1]
        self.assertEqual(
            float_compare(ml1.debit, wiz.fund_amount, precision_digits=2),
            0)
        self.assertTrue(float_is_zero(ml1.credit, precision_digits=2))
        self.assertEqual(ml1.account_id.id, self.account.id)
        self.assertEqual(
            float_compare(ml2.credit, wiz.fund_amount, precision_digits=2),
            0)
        self.assertTrue(float_is_zero(ml2.debit, precision_digits=2))
        self.assertEqual(ml2.account_id.id, self.payable_account.id)
Example #25
0
    def _get_invoiced(self):
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        for order in self:
            if order.state != 'purchase':
                order.invoice_status = 'no'
                continue

            if any(float_compare(line.qty_invoiced, line.product_qty, precision_digits=precision) == -1 for line in order.order_line):
                order.invoice_status = 'to invoice'
            elif all(float_compare(line.qty_invoiced, line.product_qty, precision_digits=precision) >= 0 for line in order.order_line):
                order.invoice_status = 'invoiced'
            else:
                order.invoice_status = 'no'
Example #26
0
    def _get_invoiced(self):
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        for order in self:
            if order.state != 'purchase':
                order.invoice_status = 'no'
                continue

            if any(float_compare(line.qty_invoiced, line.product_qty, precision_digits=precision) == -1 for line in order.order_line):
                order.invoice_status = 'to invoice'
            elif all(float_compare(line.qty_invoiced, line.product_qty, precision_digits=precision) >= 0 for line in order.order_line):
                order.invoice_status = 'invoiced'
            else:
                order.invoice_status = 'no'
Example #27
0
    def _calc_new_qty_price(self, procurement, po_line=None, cancel=False):
        if not po_line:
            po_line = procurement.purchase_line_id

        qty = self.env['product.uom']._compute_qty(procurement.product_uom.id, procurement.product_qty,
                                                   procurement.product_id.uom_po_id.id)
        if cancel:
            qty = -qty

        supplierinfo = self.env['product.supplierinfo']. \
            search([('name', '=', po_line.order_id.partner_id.id),
                    ('product_tmpl_id', '=', po_line.product_id.product_tmpl_id.id)], order='sequence, id', limit=1)

        # Make sure we use the minimum quantity of the partner corresponding to the PO.
        # This does not apply in case of dropshipping
        supplierinfo_min_qty = 0.0
        if po_line.order_id.location_id.usage != 'customer' and supplierinfo:
            supplierinfo_min_qty = self.env['product.uom']. \
                _compute_qty(supplierinfo.product_uom.id, supplierinfo.min_qty,
                             po_line.product_id.uom_po_id.id)

        if supplierinfo_min_qty == 0.0 and not self.env.context.get('focus_on_procurements'):
            qty += po_line.product_qty
        elif self.env.context.get('cancelling_active_proc'):
            qty = sum([x.product_qty for x in po_line.procurement_ids if x.state != 'cancel' and x != procurement])
        else:
            # Recompute quantity by adding existing running procurements.
            for proc in po_line.procurement_ids:
                qty += self.env['product.uom']. \
                    _compute_qty(proc.product_uom.id, proc.product_qty,
                                 proc.product_id.uom_po_id.id) if proc.state == 'running' else 0.0
            qty = max(qty, supplierinfo_min_qty) if qty > 0.0 else 0.0

        price = po_line.price_unit

        if supplierinfo:
            packaging_number = self.env['product.uom']. \
                _compute_qty(supplierinfo.product_uom.id, supplierinfo.packaging_qty,
                             po_line.product_id.uom_po_id.id)
            if float_compare(packaging_number, 0.0, precision_rounding=procurement.product_uom.rounding) == 0:
                packaging_number = 1
            if float_compare(qty, 0.0, precision_rounding=procurement.product_uom.rounding) != 0:
                qty = max(qty, supplierinfo.min_qty)
            if float_compare(qty % packaging_number, 0.0, precision_rounding=procurement.product_uom.rounding) != 0:
                qty = (qty // packaging_number + 1) * packaging_number

        if qty != po_line.product_qty:
            pricelist = po_line.order_id.partner_id.property_product_pricelist_purchase
            price = pricelist.with_context(uom=procurement.product_uom.id). \
                price_get(procurement.product_id.id, qty, po_line.order_id.partner_id.id)[pricelist.id]
        return qty, price
Example #28
0
    def interval_get_multi(self, cr, uid, date_and_hours_by_cal, resource=False, byday=True):
        def group(lst, key):
            lst.sort(key=itemgetter(key))
            grouped = groupby(lst, itemgetter(key))
            return dict([(k, [v for v in itr]) for k, itr in grouped])
        # END group

        cr.execute("select calendar_id, dayofweek, hour_from, hour_to from resource_calendar_attendance order by hour_from")
        hour_res = cr.dictfetchall()
        hours_by_cal = group(hour_res, 'calendar_id')

        results = {}

        for d, hours, id in date_and_hours_by_cal:
            dt_from = datetime.strptime(d, '%Y-%m-%d %H:%M:%S')
            if not id:
                td = int(hours)*3
                results[(d, hours, id)] = [(dt_from, dt_from + timedelta(hours=td))]
                continue

            dt_leave = self._get_leaves(cr, uid, id, resource)
            todo = hours
            result = []
            maxrecur = 100
            current_hour = dt_from.hour
            while float_compare(todo, 0, 4) and maxrecur:
                for (hour_from,hour_to) in [(item['hour_from'], item['hour_to']) for item in hours_by_cal[id] if item['dayofweek'] == str(dt_from.weekday())]:
                    leave_flag  = False
                    if (hour_to>current_hour) and float_compare(todo, 0, 4):
                        m = max(hour_from, current_hour)
                        if (hour_to-m)>todo:
                            hour_to = m+todo
                        dt_check = dt_from.strftime('%Y-%m-%d')
                        for leave in dt_leave:
                            if dt_check == leave:
                                dt_check = datetime.strptime(dt_check, '%Y-%m-%d') + timedelta(days=1)
                                leave_flag = True
                        if leave_flag:
                            break
                        else:
                            d1 = datetime(dt_from.year, dt_from.month, dt_from.day) + timedelta(hours=int(math.floor(m)), minutes=int((m%1) * 60))
                            d2 = datetime(dt_from.year, dt_from.month, dt_from.day) + timedelta(hours=int(math.floor(hour_to)), minutes=int((hour_to%1) * 60))
                            result.append((d1, d2))
                            current_hour = hour_to
                            todo -= (hour_to - m)
                dt_from += timedelta(days=1)
                current_hour = 0
                maxrecur -= 1
            results[(d, hours, id)] = result
        return results
 def _compute_remarks(self):
     for rec in self:
         # Rolling > Released
         if float_compare(rec.rolling, rec.released_amount, 2) == 1:
             rolling = '{:,.2f}'.format(rec.rolling)
             diff = '{:,.2f}'.format(rec.rolling - rec.released_amount)
             rec.remarks = _('Rolling Amount: %s\n'
                             'Rolling > Released = %s') % (rolling, diff)
         # Rolling < Released
         if float_compare(rec.rolling, rec.released_amount, 2) == -1:
             rolling = '{:,.2f}'.format(rec.rolling)
             diff = '{:,.2f}'.format(rec.released_amount - rec.rolling)
             rec.remarks = _('Rolling Amount: %s\n'
                             'Rolling < Released = %s') % (rolling, diff)
Example #30
0
 def _create_link_for_product(operation_id, product_id, qty):
     '''method that creates the link between a given operation and move(s) of given product, for the given quantity.
     Returns True if it was possible to create links for the requested quantity (False if there was not enough quantity on stock moves)'''
     qty_to_assign = qty
     prod_obj = self.pool.get("product.product")
     product = prod_obj.browse(cr, uid, product_id)
     rounding = product.uom_id.rounding
     qtyassign_cmp = float_compare(qty_to_assign, 0.0, precision_rounding=rounding)
     if prod2move_ids.get(product_id):
         while prod2move_ids[product_id] and qtyassign_cmp > 0:
             qty_on_link = _create_link_for_index(operation_id, 0, product_id, qty_to_assign, quant_id=False)
             qty_to_assign -= qty_on_link
             qtyassign_cmp = float_compare(qty_to_assign, 0.0, precision_rounding=rounding)
     return qtyassign_cmp == 0
Example #31
0
    def testBalanceWithManyAccounts(self):
        """Test balance of multiple funds using one ledger account"""

        VoucherWizard = self.env['account.pettycash.fund.voucher']

        # Create first fund and voucher
        #
        pcf1 = self.create_fund('Petty Cash Fund 01')
        vwiz_vals = {
            'fund': pcf1.id,
            'date': datetime.today().date(),
            'partner': pcf1.custodian_partner.id,
            'lines': [
                (0, 0, {
                    'expense_account': self.expense_account.id,
                    'amount': 100.00}),
            ]
        }
        vwiz1 = VoucherWizard.sudo(self.uidOwner).create(vwiz_vals)
        vwiz1.sudo(self.uidOwner).create_voucher()

        # Create second fund and voucher
        #
        pcf2 = self.create_fund('Petty Cash Fund 02')
        vwiz2_vals = {
            'fund': pcf2.id,
            'date': datetime.today().date(),
            'lines': [
                (0, 0, {
                    'expense_account': self.expense_account.id,
                    'amount': 150.16}),
            ]
        }
        vwiz2 = VoucherWizard.sudo(self.uidOwner).create(vwiz2_vals)
        vwiz2.create_voucher()

        balance1 = pcf1.amount
        for l in vwiz1.lines:
            balance1 -= l.amount
        balance2 = pcf2.amount
        for l in vwiz2.lines:
            balance2 -= l.amount

        self.assertEqual(
            float_compare(pcf1.balance, balance1, precision_digits=2),
            0)
        self.assertEqual(
            float_compare(pcf2.balance, balance2, precision_digits=2),
            0)
Example #32
0
    def testIncreaseFundAmount(self):
        """Test increasing the fund amount"""

        # Create a fund
        pcf1 = self.create_fund('Petty Cash Fund 01')
        self.assertEqual(pcf1.state, 'open')

        # Increase the fund
        Wizard = self.env['account.pettycash.fund.change']
        ctx = self.env.context.copy()
        ctx.update({'active_id': pcf1.id})
        wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({
            'new_amount': 10000.00,
            'payable_account': self.payable_account.id,
            'effective_date': datetime.today().date(),
            'custodian': self.uidInv.id,
            'fund_name': 'Changed name',
        })
        self.assertEqual(wiz.fund.id, pcf1.id)
        self.assertEqual(
            float_compare(wiz.fund_amount, pcf1.amount, precision_digits=2),
            0)
        diff_amount = wiz.new_amount - wiz.fund_amount

        wiz.sudo(self.uidFinMgr).change_fund()

        self.assertEqual(pcf1.name, 'Changed name')
        self.assertEqual(pcf1.custodian.id, self.uidInv.id)
        self.assertEqual(
            float_compare(pcf1.amount, 10000.00, precision_digits=2),
            0)
        self.assertEqual(wiz.move.state, 'posted')

        # Check ledger accounts have been updated properly:
        # Accounts payable should have a credit for the fund amount.
        # The fund account should have a debit for same amount.
        move = wiz.move
        ml1 = move.line_id[0]
        ml2 = move.line_id[1]
        self.assertEqual(
            float_compare(ml1.debit, diff_amount, precision_digits=2),
            0)
        self.assertTrue(float_is_zero(ml1.credit, precision_digits=2))
        self.assertEqual(ml1.account_id.id, self.account.id)
        self.assertEqual(
            float_compare(ml2.credit, diff_amount, precision_digits=2),
            0)
        self.assertTrue(float_is_zero(ml2.debit, precision_digits=2))
        self.assertEqual(ml2.account_id.id, self.payable_account.id)
Example #33
0
 def _quant_split(self, quant, qty):
     prec = quant.product_id.uom_id.rounding
     result = super(StockQuant, self)._quant_split(quant, qty)
     old_neg = float_compare(float_round(quant.qty, precision_rounding=prec), 0, precision_rounding=prec) <= 0
     new_neg = False
     if result:
         new_neg = float_compare(float_round(result.qty, precision_rounding=prec), 0, precision_rounding=prec) <= 0
     if (not config["test_enable"] or self.env.context.get('stock_forbid_negative_quants')) \
             and (old_neg or new_neg) and quant.product_id.type == 'product':
         raise ValueError(_("Quant split: you are not allowed to create a negative or null quant. "
                            "Product: %s, Quant qty: %s, Required reduction to: %s, Location: %s,"
                            " Lot: %s, Package: %s") % (quant.product_id.display_name, quant.qty, qty,
                                                        quant.location_id.complete_name, quant.lot_id.name or '-',
                                                        quant.package_id.name or '-'))
     return result
Example #34
0
 def recalculate_state(self, move):
     reserved = move.reserved_availability
     uom_qty = move.product_uom_qty
     if not reserved:
         move.write({'state': 'confirmed', 'partially_available': False})
     elif float_compare(reserved, uom_qty, precision_rounding=0.01) == 0:
         move.write({'state': 'assigned', 'partially_available': False})
     elif float_compare(reserved, uom_qty, precision_rounding=0.01) < 0:
         move.write({'state': 'confirmed', 'partially_available': True})
     else:
         raise except_orm(
             _('Error'),
             _('reserved quantity (%s) greater than move \
                             quantity (%s)' % (reserved, uom_qty)))
     return
Example #35
0
    def test_01_action_scan_bvr(self):
        """ Check state of wizard passe in need information state
        if no partner has an adherent number equal to the one in
        bvr scan line

        0100003949753>120000000000234478943216899+ 010001628>

        """
        cr, uid = self.cr, self.uid
        bvr_string = '0100003949753>120000000000234478943216899+ 010001628>'
        wizard_id = self.ScanBVR.create(
            cr, uid, {'bvr_string': bvr_string,
                      'journal_id': self.purchase_journal_id,
                      }, context={})
        act_win = self.ScanBVR.validate_bvr_string(
            cr, uid, [wizard_id], context={})
        wizard = self.ScanBVR.browse(
            cr, uid, wizard_id, context=None)
        assert wizard.state == 'need_extra_info'

        self.ScanBVR.write(
                cr, uid, wizard.id, {
                    'partner_id': self.partner1.id,
                    'bank_account_id': self.partner1bank1.id,
                    },
                context={})

        act_win = self.ScanBVR.validate_bvr_string(
            cr, uid, [wizard_id], context={})
        assert act_win['res_id']
        assert self.partner1bank1.bvr_adherent_num

        new_invoice = self.Invoice.browse(cr, uid, act_win['res_id'])
        assert float_compare(new_invoice.amount_total, 3949.75,
                             precision_rounding=0.01) == 0
Example #36
0
 def _prepare_invoice_line_from_po_line(self, line):
     if line.product_id.purchase_method == 'purchase':
         qty = line.product_qty - line.qty_invoiced
     else:
         qty = line.qty_received - line.qty_invoiced
     if float_compare(qty, 0.0, precision_rounding=line.product_uom.rounding) <= 0:
         qty = 0.0
     taxes = line.taxes_id
     invoice_line_tax_ids = self.purchase_id.fiscal_position_id.map_tax(taxes)
     invoice_line = self.env['account.invoice.line']
     data = {
         'purchase_line_id': line.id,
         'name': line.name,
         'origin': self.purchase_id.origin,
         'uom_id': line.product_uom.id,
         'product_id': line.product_id.id,
         'account_id': invoice_line.with_context({'journal_id': self.journal_id.id, 'type': 'in_invoice'})._default_account(),
         'price_unit': line.order_id.currency_id.compute(line.price_unit, self.currency_id, round=False),
         'quantity': qty,
         'discount': 0.0,
         'account_analytic_id': line.account_analytic_id.id,
         'invoice_line_tax_ids': invoice_line_tax_ids.ids
     }
     account = invoice_line.get_invoice_line_account('in_invoice', line.product_id, self.purchase_id.fiscal_position_id, self.env.user.company_id)
     if account:
         data['account_id'] = account.id
     return data
Example #37
0
    def purchase_order_change(self):
        result = []
        if not self.purchase_id:
            return {}
        if not self.partner_id:
            self.partner_id = self.purchase_id.partner_id.id

        # Keep existing lines. We want to be able to add several PO on the same invoice.
        for line in self.invoice_line_ids:
            result.append(
                {
                    "purchase_line_id": line.purchase_line_id.id,
                    "name": line.name,
                    "origin": line.origin,
                    "uom_id": line.uom_id.id,
                    "product_id": line.product_id.id,
                    "account_id": line.account_id.id,
                    "price_unit": line.price_unit,
                    "quantity": line.quantity,
                    "discount": line.discount,
                    "account_analytic_id": line.account_analytic_id.id,
                    "invoice_line_tax_ids": line.invoice_line_tax_ids.ids,
                }
            )

        for line in self.purchase_id.order_line:
            if line.product_id.purchase_method == "purchase":
                qty = line.product_qty - line.qty_invoiced
            else:
                qty = line.qty_received - line.qty_invoiced
            if float_compare(qty, 0.0, precision_rounding=line.product_uom.rounding) <= 0:
                qty = 0.0
            taxes = line.taxes_id or line.product_id.supplier_taxes_id
            invoice_line_tax_ids = self.purchase_id.fiscal_position_id.map_tax(taxes)
            data = {
                "purchase_line_id": line.id,
                "name": line.name,
                "origin": self.purchase_id.origin,
                "uom_id": line.product_uom.id,
                "product_id": line.product_id.id,
                "account_id": self.env["account.invoice.line"]
                .with_context({"journal_id": self.journal_id.id, "type": "in_invoice"})
                ._default_account(),
                "price_unit": line.price_unit,
                "quantity": qty,
                "discount": 0.0,
                "account_analytic_id": line.account_analytic_id.id,
                "invoice_line_tax_ids": invoice_line_tax_ids.ids,
            }
            account = self.env["account.invoice.line"].get_invoice_line_account(
                "in_invoice", line.product_id, self.purchase_id.fiscal_position_id, self.env.user.company_id
            )
            if account:
                data["account_id"] = account.id
            result.append(data)

        self.invoice_line_ids = False  # To avoid duplicates
        self.invoice_line_ids = result
        self.purchase_id = False
        return {}
Example #38
0
    def _swedish_add_invoice_line(self, cr, uid, invoice, amounts,
                                  rounded_total, delta, context=None):
        """ Create a invoice_line with the diff of rounding """
        invoice_line_obj = self.pool.get('account.invoice.line')
        obj_precision = self.pool.get('decimal.precision')
        prec = obj_precision.precision_get(cr, uid, 'Account')

        company = invoice.company_id
        if not invoice.global_round_line_id:
            new_invoice_line = {
                'name': _('Rounding'),
                'price_unit': -delta,
                'account_id': company.tax_calculation_rounding_account_id.id,
                'invoice_id': invoice.id,
                'is_rounding': True,
            }
            invoice_line_obj.create(cr, uid, new_invoice_line, context=context)
        elif float_compare(invoice.global_round_line_id.price_unit, -delta,
                           precision_digits=prec) != 0:
            invoice_line_obj.write(
                cr, uid, invoice.global_round_line_id.id,
                {'price_unit': -delta}, context=context)

        amount_untaxed = float_round(amounts['amount_untaxed'] - delta,
                                     precision_digits=prec)
        return {'amount_total': rounded_total,
                'amount_untaxed': amount_untaxed}
Example #39
0
    def _remita_form_get_invalid_parameters(self,
                                            cr,
                                            uid,
                                            tx,
                                            data,
                                            context=None):
        invalid_parameters = []

        if tx.acquirer_reference and data.get(
                'transaction_id') != tx.acquirer_reference:
            invalid_parameters.append(
                ('Transaction Id', data.get('transaction_id'),
                 tx.acquirer_reference))
        # check what is buyed

        #Use transaction_id to pull in more info from Remita
        transaction_id = data.get('transaction_id')
        #transaction_id = '559f55426a93a'
        response = urllib2.urlopen(
            'https://remita.com/?v_transaction_id=%s&type=json' %
            (transaction_id))
        myTx = json.load(response)

        if float_compare(float(myTx.get('total', '0.0')), tx.amount, 2) != 0:
            invalid_parameters.append(
                ('Amount', data.get('total'), '%.2f' % tx.amount))
#        if data.get('BRQ_CURRENCY') != tx.currency_id.name:
#            invalid_parameters.append(('Currency', data.get('BRQ_CURRENCY'), tx.currency_id.name))

        return invalid_parameters
Example #40
0
    def _swedish_add_invoice_line(self, invoice, rounded_total, delta):
        """ Create a invoice_line with the diff of rounding """

        invoice_line_obj = self.env['account.invoice.line']
        obj_precision = self.env['decimal.precision']
        prec = obj_precision.precision_get('Account')

        company = invoice.company_id
        if not invoice.global_round_line_id.id:
            new_invoice_line = {
                'name': _('Rounding'),
                'price_unit': -delta,
                'account_id': company.tax_calculation_rounding_account_id.id,
                'invoice_id': invoice.id,
                'is_rounding': True,
            }
            invoice_line_obj.create(new_invoice_line)
        elif float_compare(invoice.global_round_line_id.price_unit,
                           -delta,
                           precision_digits=prec) != 0:
            invoice_line_obj.write(invoice.global_round_line_id.id,
                                   {'price_unit': -delta})

        amount_untaxed = float_round(invoice.amount_untaxed - delta,
                                     precision_digits=prec)
        return {
            'amount_total': rounded_total,
            'amount_untaxed': amount_untaxed
        }
Example #41
0
    def _frst_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []

        # Compare the local amount with the amount from the PP
        if float_compare(float(data.get('amount', '0.0')), tx.amount, 2) != 0:
            invalid_parameters.append(('amount', data.get('amount'), '%.2f' % tx.amount))

        # Compare the local currency with the currency of the pp
        if data.get('currency') != tx.currency_id.name:
            invalid_parameters.append(('currency', data.get('currency'), tx.currency_id.name))

        # Check IBAN
        if not data.get('frst_iban'):
            invalid_parameters.append(('frst_iban', data.get('frst_iban'), 'At least some value '))

        # Check BIC
        if not data.get('frst_bic'):
            invalid_parameters.append(('frst_bic', data.get('frst_bic'), 'At least some Value'))

        info_msg = 'FRST Payment Transaction: Invalid Parameters %s' % (pprint.pformat(invalid_parameters))
        _logger.info(info_msg)
        print '----'
        print info_msg
        print '----'

        return invalid_parameters
Example #42
0
 def _get_bom_delivered(self, line):
     precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
     bom_delivered = {}
     # There is no dependencies between purchase and mrp
     if 'mrp.bom' in self.env:
         # In the case of a kit, we need to check if all components are shipped. We use a all or
         # nothing policy. A product can have several BoMs, we don't know which one was used when the
         # delivery was created.
         for bom in line.product_id.product_tmpl_id.bom_ids:
             if bom.type != 'phantom':
                 continue
             bom_delivered[bom.id] = False
             product_uom_qty_bom = self.env['product.uom']._compute_qty_obj(line.product_uom, line.product_qty, bom.product_uom)
             bom_exploded = self.env['mrp.bom']._bom_explode(bom, line.product_id, product_uom_qty_bom)[0]
             for bom_line in bom_exploded:
                 qty = 0.0
                 for move in line.move_ids:
                     if move.state == 'done' and move.product_id.id == bom_line.get('product_id', False):
                         qty += self.env['product.uom']._compute_qty(move.product_uom.id, move.product_uom_qty, bom_line['product_uom'])
                 if float_compare(qty, bom_line['product_qty'], precision_digits=precision) < 0:
                     bom_delivered[bom.id] = False
                     break
                 else:
                     bom_delivered[bom.id] = True
     return bom_delivered
 def do_detailed_transfer(self):
     stock_loc_id = self.picking_id.picking_type_id.warehouse_id.lot_stock_id.id
     for line in self.item_ids:
         if line.product_id.type == 'product':
             if line.sourceloc_id.id not in self.env['stock.location'].search(
                     [('id', 'child_of', stock_loc_id)])._ids:
                 continue
             quant_vals = [('product_id', '=', line.product_id.id),
                           ('lot_id', '=', line.lot_id and line.lot_id.id or
                            False),
                           ('location_id', '=', line.sourceloc_id.id),
                           '|', ('reservation_id.picking_id', '=',
                                 self.picking_id.id),
                           ('reservation_id', '=', False)]
             quants = self.env['stock.quant'].search(quant_vals)
             total_qty = sum([x['qty'] for x in quants.read(['qty'])])
             total_qty_uom = self.env['product.uom']._compute_qty(
                 line.product_id.uom_id.id, total_qty,
                 line.product_uom_id.id)
             difference = float_compare(
                 total_qty_uom, line.quantity,
                 precision_rounding=line.product_uom_id.rounding)
             if difference < 0:
                 raise exceptions.Warning(
                     _('Quantity error'),
                     _('Not found enought stock in %s for product %s') %
                     (line.sourceloc_id.name, line.product_id.name))
     return super(StockTransferDetails, self).do_detailed_transfer()
Example #44
0
 def check_over_request_limit(self):
     self.ensure_one()
     Request = self.env['purchase.request']
     for po_line in self.order_line:
         subtotal_value = 0.0
         list_product = []
         list_request = []
         request_lines = po_line.requisition_line_id.purchase_request_lines
         for req_line in request_lines:
             subtotal_value += req_line.price_subtotal
             if req_line.name not in list_product:
                 list_product.append(req_line.name)
             if req_line.request_id.id not in list_request:
                 list_request.append(req_line.request_id.id)
         ref_requests = Request.search([('request_ref_id', 'in',
                                         list_request)])
         if not ref_requests:
             continue
         for ref_req in ref_requests:
             for ref_req_line in ref_req.line_ids:
                 if ref_req_line.name in list_product:
                     subtotal_value += ref_req_line.price_subtotal
         # When order amount > pr amount, do not allow.
         if float_compare(po_line.product_qty * po_line.price_unit,
                          subtotal_value, 2) == 1:
             raise ValidationError(
                 _("Some order line's price is over than request's price"))
     return True
Example #45
0
 def _check_balance(self, vals):
     """Check if move is balanced"""
     line_dicts = [y[2] for y in vals['line_id']]
     debit = sum(x.get('debit') or 0.0 for x in line_dicts)
     credit = sum(x.get('credit') or 0.0 for x in line_dicts)
     if float_compare(debit, credit, precision_digits=2):
         raise ValueError('Move is not balanced %s %s' % (debit, credits))
Example #46
0
    def _bpd_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []

        if float_compare(float(data.get('amount', '0.0')), tx.amount, 2) != 0:
            invalid_parameters.append(('amount', data.get('amount'), '%.2f' % tx.amount))
        if data.get('currency') != tx.currency_id.name:
            invalid_parameters.append(('currency', data.get('currency'), tx.currency_id.name))

        tx_bpd_request = {}
        if tx.acquirer_id.environment == 'prod':
            tx_bpd_request.update({
                "Channel": tx.acquirer_id.bpd_channel_prod,
                "Store": tx.acquirer_id.bpd_store_prod,
                "PosInputMode": tx.acquirer_id.bpd_posinputmode_prod
            })
            tx_url = tx.acquirer_id.bpd_url_prod
            Auth1 = tx.acquirer_id.bpd_auth1_prod
            Auth2 = tx.acquirer_id.bpd_auth2_prod
        else:
            tx_bpd_request.update({
                "Channel": tx.acquirer_id.bpd_channel_test,
                "Store": tx.acquirer_id.bpd_store_test,
                "PosInputMode": tx.acquirer_id.bpd_posinputmode_test
            })
            tx_url = tx.acquirer_id.bpd_url_test
            Auth1 = tx.acquirer_id.bpd_auth1_test
            Auth2 = tx.acquirer_id.bpd_auth2_test
            # cc_month, cc_year = data.get("cc_expiry").replace(" ", "").split("/")
        tx_bpd_request.update({
            # "CardNumber": u"4012000077777777",
            "CardNumber": int(data.get("cc_number").replace(" ", "")),
            "Expiration": 201701,#int("20%s%s" % (cc_year, cc_month)),
            "CVC": 201,#int(data.get("cc_cvc")),
            "TrxType": "Sale",
            "Amount": 100,#'%d' % int(float_round(float(data['amount']), 2) * 100),
            "CurrencyPosCode": "$" if data.get("currency") == u"DOP" else u"U$S",
            "Payments": "1",
            "Plan": "0",
            "AcquirerRefData": "1",
            "CustomerServicePhone": tx.acquirer_id.service_phone,
            "OrderNumber": data['reference'],
            "ECommerceUrl": tx.acquirer_id.ecommerceurl})

        request = urllib2.Request(tx_url, json.dumps(tx_bpd_request))
        request.add_header('Auth1', Auth1)
        request.add_header('Auth2', Auth2)
        request.add_header('Content-type', 'application/json')
        request = urllib2.urlopen(request)
        result = request.read()
        print result
        _logger.info('=========================BPD DEBUG RESPONSE BLOCK===========================')  # debug
        from pprint import pprint as pp

        _logger.info(pp(json.loads(result)))  # debug
        _logger.info('=========================BPD DEBUG RESPONSE BLOCK===========================')  # debug

        invalid_parameters.append(('cc_cvc', data.get('currency'), tx.currency_id.name))

        return invalid_parameters
Example #47
0
    def _transfer_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []

        if float_compare(float(data.get("amount", "0.0")), tx.amount, 2) != 0:
            invalid_parameters.append(("amount", data.get("amount"), "%.2f" % tx.amount))
        if data.get("currency") != tx.currency_id.name:
            invalid_parameters.append(("currency", data.get("currency"), tx.currency_id.name))

        return invalid_parameters
Example #48
0
    def _authorize_form_get_invalid_parameters(self, tx, data):
        invalid_parameters = []

        if self.acquirer_reference and data.get("x_trans_id") != self.acquirer_reference:
            invalid_parameters.append(("Transaction Id", data.get("x_trans_id"), self.acquirer_reference))
        # check what is buyed
        if float_compare(float(data.get("x_amount", "0.0")), tx.amount, 2) != 0:
            invalid_parameters.append(("Amount", data.get("x_amount"), "%.2f" % tx.amount))
        return invalid_parameters
Example #49
0
    def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, group_id, context=None):
        ''' prepare the stock move data from the PO line. This function returns a list of dictionary ready to be used in stock.move's create()'''
        product_uom = self.pool.get('product.uom')
        checke_tax = order_line.checke_tax
        if order_line.product_uom.id != order_line.product_id.uom_id.id:
            checke_tax *= order_line.product_uom.factor / order_line.product_id.uom_id.factor
        if order.currency_id.id != order.company_id.currency_id.id:
            #we don't round the price_unit, as we may want to store the standard price with more digits than allowed by the currency
            checke_tax = self.pool.get('res.currency').compute(cr, uid, order.currency_id.id, order.company_id.currency_id.id, checke_tax, round=False, context=context)
        res = []
        move_template = {
            'name': order_line.name or '',
            'product_id': order_line.product_id.id,
            'product_uom': order_line.product_uom.id,
            'product_uos': order_line.product_uom.id,
            'date': order.date_order,
            'date_expected': fields.date.date_to_datetime(self, cr, uid, order_line.date_planned, context),
            'location_id': order.partner_id.property_stock_supplier.id,
            'location_dest_id': order.location_id.id,
            'picking_id': picking_id,
            'partner_id': order.dest_address_id.id,
            'move_dest_id': False,
            'state': 'draft',
            'purchase_line_id': order_line.id,
            'company_id': order.company_id.id,
            'checke_tax': checke_tax,
            'picking_type_id': order.picking_type_id.id,
            'group_id': group_id,
            'procurement_id': False,
            'origin': order.name,
            'route_ids': order.picking_type_id.warehouse_id and [(6, 0, [x.id for x in order.picking_type_id.warehouse_id.route_ids])] or [],
            'warehouse_id':order.picking_type_id.warehouse_id.id,
            'invoice_state': order.invoice_method == 'picking' and '2binvoiced' or 'none',
        }

        diff_quantity = order_line.product_qty
        for procurement in order_line.procurement_ids:
            procurement_qty = product_uom._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, to_uom_id=order_line.product_uom.id)
            tmp = move_template.copy()
            tmp.update({
                'product_uom_qty': min(procurement_qty, diff_quantity),
                'product_uos_qty': min(procurement_qty, diff_quantity),
                'move_dest_id': procurement.move_dest_id.id,  #move destination is same as procurement destination
                'group_id': procurement.group_id.id or group_id,  #move group is same as group of procurements if it exists, otherwise take another group
                'procurement_id': procurement.id,
                'invoice_state': procurement.rule_id.invoice_state or (procurement.location_id and procurement.location_id.usage == 'customer' and procurement.invoice_state=='2binvoiced' and '2binvoiced') or (order.invoice_method == 'picking' and '2binvoiced') or 'none', #dropship case takes from sale
                'propagate': procurement.rule_id.propagate,
            })
            diff_quantity -= min(procurement_qty, diff_quantity)
            res.append(tmp)
        #if the order line has a bigger quantity than the procurement it was for (manually changed or minimal quantity), then
        #split the future stock move in two because the route followed may be different.
        if float_compare(diff_quantity, 0.0, precision_rounding=order_line.product_uom.rounding) > 0:
            move_template['product_uom_qty'] = diff_quantity
            move_template['product_uos_qty'] = diff_quantity
            res.append(move_template)
        return res
Example #50
0
    def _prepare_order_line_move(self, order, order_line, picking_id, group_id):
        product_uom = self.env['product.uom']
        price_unit = order_line.price_unit
        if order_line.product_uom.id != order_line.product_id.uom_id.id:
            price_unit *= order_line.product_uom.factor / order_line.product_id.uom_id.factor
        if order.currency_id.id != order.company_id.currency_id.id:
            #we don't round the price_unit, as we may want to store the standard price with more digits than allowed by the currency
            price_unit = self.env['res.currency'].compute(order.currency_id.id, order.company_id.currency_id.id, price_unit, round=False)
        res = []
        move_template = {
            'name': order_line.name or '',
            'product_id': order_line.product_id.id,
            'product_uom': order_line.product_uom.id,
            'product_uos': order_line.product_uom.id,
            'date': order.date,
            'date_expected': self.date_to_datetime(self, order_line.date_planned),
            'location_id': order_line.supplier_id.property_stock_supplier.id,
            'location_dest_id': order.location_id.id,
            'picking_id': picking_id.id,
            'partner_id': order_line.supplier_id.id,
            'move_dest_id': False,
            'state': 'draft',
            'purchase_line_id': order_line.id,
            'company_id': order.company_id.id,
            'price_unit': price_unit,
            'picking_type_id': order.picking_type_id.id,
            'group_id': group_id.id,
            'procurement_id': False,
            'origin': order.number,
            'route_ids': order.picking_type_id.warehouse_id and [(6, 0, [x.id for x in order.picking_type_id.warehouse_id.route_ids])] or [],
            'warehouse_id':order.picking_type_id.warehouse_id.id,
            'invoice_state': '2binvoiced',#For moment use static. Todo Ecosoft Check.
        }

        diff_quantity = order_line.product_qty
        for procurement in order_line.procurement_ids:
            procurement_qty = product_uom._compute_qty(procurement.product_uom.id, procurement.product_qty, to_uom_id=order_line.product_uom.id)
            tmp = move_template.copy()
            tmp.update({
                'product_uom_qty': min(procurement_qty, diff_quantity),
                'product_uos_qty': min(procurement_qty, diff_quantity),
                'move_dest_id': procurement.move_dest_id.id,  #move destination is same as procurement destination
                'group_id': procurement.group_id and procurement.group_id.id or group_id and group_id.id or False,  #move group is same as group of procurements if it exists, otherwise take another group
                'procurement_id': procurement.id,
                #'invoice_state': procurement.rule_id.invoice_state or (procurement.location_id and procurement.location_id.usage == 'customer' and procurement.invoice_state=='2binvoiced' and '2binvoiced') or (order.invoice_method == 'picking' and '2binvoiced') or 'none', #dropship case takes from sale
                'invoice_state': '2binvoiced',
                'propagate': procurement.rule_id.propagate,
            })
            diff_quantity -= min(procurement_qty, diff_quantity)
            res.append(tmp)
        #if the order line has a bigger quantity than the procurement it was for (manually changed or minimal quantity), then
        #split the future stock move in two because the route followed may be different.
        if float_compare(diff_quantity, 0.0, precision_rounding=order_line.product_uom.rounding) > 0:
            move_template['product_uom_qty'] = diff_quantity
            move_template['product_uos_qty'] = diff_quantity
            res.append(move_template)
        return res
Example #51
0
    def purchase_order_change(self):
        result = []
        if not self.purchase_id:
            return {}
        if not self.partner_id:
            self.partner_id = self.purchase_id.partner_id.id

        # Keep existing lines. We want to be able to add several PO on the same invoice.
        for line in self.invoice_line_ids:
            result.append({
                'purchase_line_id': line.purchase_line_id.id,
                'name': line.name,
                'origin': line.origin,
                'uom_id': line.uom_id.id,
                'product_id': line.product_id.id,
                'account_id': line.account_id.id,
                'price_unit': line.price_unit,
                'quantity': line.quantity,
                'discount': line.discount,
                'account_analytic_id': line.account_analytic_id.id,
                'invoice_line_tax_ids': line.invoice_line_tax_ids.ids,
            })

        for line in self.purchase_id.order_line:
            # Load a PO line only once
            if line in self.invoice_line_ids.mapped('purchase_line_id'):
                continue
            if line.product_id.purchase_method == 'purchase':
                qty = line.product_qty - line.qty_invoiced
            else:
                qty = line.qty_received - line.qty_invoiced
            if float_compare(qty, 0.0, precision_rounding=line.product_uom.rounding) <= 0:
                qty = 0.0
            taxes = line.taxes_id or line.product_id.supplier_taxes_id
            invoice_line_tax_ids = self.purchase_id.fiscal_position_id.map_tax(taxes)
            data = {
                'purchase_line_id': line.id,
                'name': line.name,
                'origin': self.purchase_id.origin,
                'uom_id': line.product_uom.id,
                'product_id': line.product_id.id,
                'account_id': self.env['account.invoice.line'].with_context({'journal_id': self.journal_id.id, 'type': 'in_invoice'})._default_account(),
                'price_unit': line.order_id.currency_id.compute(line.price_unit, self.currency_id),
                'quantity': qty,
                'discount': 0.0,
                'account_analytic_id': line.account_analytic_id.id,
                'invoice_line_tax_ids': invoice_line_tax_ids.ids
            }
            account = self.env['account.invoice.line'].get_invoice_line_account('in_invoice', line.product_id, self.purchase_id.fiscal_position_id, self.env.user.company_id)
            if account:
                data['account_id'] = account.id
            result.append(data)

        self.invoice_line_ids = False # To avoid duplicates
        self.invoice_line_ids = result
        self.purchase_id = False
        return {}
    def _invoice_form_get_invalid_parameters(self, tx, data):
        invalid_parameters = []

        if float_compare(float(data.get('amount', '0.0')), tx.amount, 2) != 0:
            invalid_parameters.append(('amount', data.get('amount'), '%.2f' % tx.amount))
        if data.get('currency') != tx.currency_id.name:
            invalid_parameters.append(('currency', data.get('currency'), tx.currency_id.name))

        return invalid_parameters
Example #53
0
    def _authorize_form_get_invalid_parameters(self, tx, data):
        invalid_parameters = []

        if self.acquirer_reference and data.get('x_trans_id') != self.acquirer_reference:
            invalid_parameters.append(('Transaction Id', data.get('x_trans_id'), self.acquirer_reference))
        # check what is buyed
        if float_compare(float(data.get('x_amount', '0.0')), tx.amount, 2) != 0:
            invalid_parameters.append(('Amount', data.get('x_amount'), '%.2f' % tx.amount))
        return invalid_parameters
    def _savedcc_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []

        if float_compare(float(data.get('amount', '0.0')), tx.amount, 2) != 0:
            invalid_parameters.append(('amount', data.get('amount'), '%.2f' % tx.amount))
        if data.get('currency') != tx.currency_id.name:
            invalid_parameters.append(('currency', data.get('currency'), tx.currency_id.name))

        return invalid_parameters
Example #55
0
    def onchange_enddate(self, cr, uid, ids, employee_id,
                         date_from, date_to, holiday_status_id, no_days, context=None):
        
        ee_obj = self.pool.get('hr.employee')
        holiday_obj = self.pool.get('hr.holidays.public')
        sched_tpl_obj = self.pool.get('hr.schedule.template')
        res = {'value': {'return_date': False}}

        if not employee_id or not date_to or (float_compare(no_days, 0.0, precision_rounding=0.01) == -1):
            return res

        if holiday_status_id:
            hs_data = self.pool.get('hr.holidays.status').read(cr, uid, holiday_status_id,
                                                               ['ex_rest_days', 'ex_public_holidays'],
                                                               context=context)
        else:
            hs_data = {}
        ex_rd = hs_data.get('ex_rest_days', False)
        ex_ph = hs_data.get('ex_public_holidays', False)

        rest_days = []
        if ex_rd:
            ee = ee_obj.browse(cr, uid, employee_id, context=context)
            if ee.contract_id and ee.contract_id.schedule_template_id:
                rest_days = sched_tpl_obj.get_rest_days(cr, uid,
                                                        ee.contract_id.schedule_template_id.id,
                                                        context=context)

        dt = datetime.strptime(date_to, OE_DTFORMAT)
        return_date = dt + timedelta(days= +1)
        while (return_date.weekday() in rest_days and ex_rd) or (holiday_obj.is_public_holiday(cr, uid, return_date.date(), context=context) and ex_ph):
            return_date += timedelta(days=1)
        res['value']['return_date'] = return_date.strftime('%B %d, %Y')
        
        # If the number of requested days is zero it means this is a partial day request.
        # Assume that a full day of work is 8 hours.
        #
        if float_compare(no_days, 1.0, precision_rounding=0.01) == -1:
            dtStart = datetime.strptime(date_from, OE_DTFORMAT)
            delta = dt - dtStart
            res['value'].update({'number_of_days_temp': float(delta.seconds) / (8.0 * 60.0 * 60.0)})
            res['value']['return_date'] = False
        return res
Example #56
0
    def _get_invoiced(self):
        precision = self.env["decimal.precision"].precision_get("Product Unit of Measure")
        for order in self:
            if order.state != "purchase":
                order.invoice_status = "no"
                continue

            if any(
                float_compare(line.qty_invoiced, line.product_qty, precision_digits=precision) == -1
                for line in order.order_line
            ):
                order.invoice_status = "to invoice"
            elif all(
                float_compare(line.qty_invoiced, line.product_qty, precision_digits=precision) >= 0
                for line in order.order_line
            ):
                order.invoice_status = "invoiced"
            else:
                order.invoice_status = "no"
    def _santander_form_get_invalid_parameters(self, tx, data):
        print "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
        invalid_parameters = []

        if (tx.acquirer_reference and data.get("ORDER_ID")) != tx.acquirer_reference:
            invalid_parameters.append(("Transaction Id", data.get("ORDER_ID"), tx.acquirer_reference))
        # check what is buyed
        if float_compare(float(data.get("AMOUNT", "0.0")) / 100, tx.amount, 2) != 0:
            invalid_parameters.append(("Amount", data.get("AMOUNT"), "%.2f" % tx.amount))
        return invalid_parameters
Example #58
0
    def _alipay_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
        invalid_parameters = []

        if tx.acquirer_reference and data.get('out_trade_no') != tx.acquirer_reference:
            invalid_parameters.append(('Transaction Id', data.get('out_trade_no'), tx.acquirer_reference))

        if float_compare(float(data.get('total_fee', '0.0')), tx.amount, 2) != 0:
            invalid_parameters.append(('Amount', data.get('total_fee'), '%.2f' % tx.amount))

        return invalid_parameters
Example #59
0
    def _create_stock_moves(self, picking):
        moves = self.env['stock.move']
        done = self.env['stock.move'].browse()
        for line in self:
            order = line.order_id
            price_unit = line.price_unit
            if line.taxes_id:
                price_unit = line.taxes_id.compute_all(price_unit, currency=line.order_id.currency_id, quantity=1.0)['total_excluded']
            if line.product_uom.id != line.product_id.uom_id.id:
                price_unit *= line.product_uom.factor / line.product_id.uom_id.factor
            if order.currency_id != order.company_id.currency_id:
                price_unit = order.currency_id.compute(price_unit, order.company_id.currency_id, round=False)

            template = {
                'name': line.name or '',
                'product_id': line.product_id.id,
                'product_uom': line.product_uom.id,
                'date': line.order_id.date_order,
                'date_expected': line.date_planned,
                'location_id': line.order_id.partner_id.property_stock_supplier.id,
                'location_dest_id': line.order_id._get_destination_location(),
                'picking_id': picking.id,
                'partner_id': line.order_id.dest_address_id.id,
                'move_dest_id': False,
                'state': 'draft',
                'purchase_line_id': line.id,
                'company_id': line.order_id.company_id.id,
                'price_unit': price_unit,
                'picking_type_id': line.order_id.picking_type_id.id,
                'group_id': line.order_id.group_id.id,
                'procurement_id': False,
                'origin': line.order_id.name,
                'route_ids': line.order_id.picking_type_id.warehouse_id and [(6, 0, [x.id for x in line.order_id.picking_type_id.warehouse_id.route_ids])] or [],
                'warehouse_id':line.order_id.picking_type_id.warehouse_id.id,
            }

            # Fullfill all related procurements with this po line
            diff_quantity = line.product_qty
            for procurement in line.procurement_ids:
                procurement_qty = procurement.product_uom._compute_qty_obj(procurement.product_uom, procurement.product_qty, line.product_uom)
                tmp = template.copy()
                tmp.update({
                    'product_uom_qty': min(procurement_qty, diff_quantity),
                    'move_dest_id': procurement.move_dest_id.id,  #move destination is same as procurement destination
                    'procurement_id': procurement.id,
                    'propagate': procurement.rule_id.propagate,
                })
                done += moves.create(tmp)
                diff_quantity -= min(procurement_qty, diff_quantity)
            if float_compare(diff_quantity, 0.0, precision_rounding=line.product_uom.rounding) > 0:
                template['product_uom_qty'] = diff_quantity
                done += moves.create(template)
        return done