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

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

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

        return [inv.id for inv in invoices.values()]
Exemple #2
0
 def invoice_line_create(self, invoice_id, qty):
     precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
     for line in self:
         if not float_is_zero(qty, precision_digits=precision):
             vals = line._prepare_invoice_line(qty=qty)
             vals.update({'invoice_id': invoice_id, 'sale_line_ids': [(6, 0, [line.id])]})
             self.env['account.invoice.line'].create(vals)
Exemple #3
0
    def action_invoice_create(self, grouped=False, final=False):
        """
        Create the invoice associated to the SO.
        :param grouped: if True, invoices are grouped by SO id. If False, invoices are grouped by
                        (partner_invoice_id, currency)
        :param final: if True, refunds will be generated if necessary
        :returns: list of created invoices
        """
        inv_obj = self.env['account.invoice']
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        invoices = {}
        references = {}
        for order in self:
            group_key = order.id if grouped else (order.partner_invoice_id.id, order.currency_id.id)
            for line in order.order_line.sorted(key=lambda l: l.qty_to_invoice < 0):
                if float_is_zero(line.qty_to_invoice, precision_digits=precision):
                    continue
                if group_key not in invoices:
                    inv_data = order._prepare_invoice()
                    invoice = inv_obj.create(inv_data)
                    references[invoice] = order
                    invoices[group_key] = invoice
                elif group_key in invoices:
                    vals = {}
                    if order.name not in invoices[group_key].origin.split(', '):
                        vals['origin'] = invoices[group_key].origin + ', ' + order.name
                    if order.client_order_ref and order.client_order_ref not in invoices[group_key].name.split(', '):
                        vals['name'] = invoices[group_key].name + ', ' + order.client_order_ref
                    invoices[group_key].write(vals)
                if line.qty_to_invoice > 0:
                    line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice)
                elif line.qty_to_invoice < 0 and final:
                    line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice)

            if references.get(invoices.get(group_key)):
                if order not in references[invoices[group_key]]:
                    references[invoice] = references[invoice] | order

        if not invoices:
            raise UserError(_('There is no invoicable line.'))


        for invoice in invoices.values():
            if not invoice.invoice_line_ids:
                raise UserError(_('There is no invoicable line.'))
            # If invoice is negative, do a refund invoice instead
            if invoice.amount_untaxed < 0:
                invoice.type = 'out_refund'
                for line in invoice.invoice_line_ids:
                    line.quantity = -line.quantity
            # Use additional field helper function (for account extensions)
            for line in invoice.invoice_line_ids:
                line._set_additional_fields(invoice)
            # Necessary to force computation of taxes. In account_invoice, they are triggered
            # by onchanges, which are not triggered when doing a create.
            invoice.compute_taxes()
            invoice.message_post_with_view('mail.message_origin_link',
                values={'self': invoice, 'origin': references[invoice]},
                subtype_id=self.env.ref('mail.mt_note').id)
        return [inv.id for inv in invoices.values()]
Exemple #4
0
    def _quants_get_order_all_locations(self, product, quantity, domain=[], orderby='in_date'):
        domain += [('product_id', '=', product.id)]
        if self.env.context.get('force_company'):
            domain += [('company_id', '=', self.env.context.get('force_company'))]
        else:
            domain += [('company_id', '=', self.env.user.company_id.id)]
        res = []
        offset = 0
        while float_compare(quantity, 0, precision_rounding=product.uom_id.rounding) > 0:
            quants = self.search(domain, order=orderby, limit=10, offset=offset)
            # for quant in quants:
            #     location_id = quant.location_id.id
            #     if location_id not in _location_usable_cache:
            #         _location_usable_cache[location_id] = product.with_context(
            #             location=location_id
            #         ).qty_usable

            if not quants:
                res.append((None, quantity))
                break
            for quant in quants:
                rounding = product.uom_id.rounding
                apply_qty = quant.qty
                if float_compare(value1=apply_qty, value2=0, precision_rounding=rounding) <= 0:
                    continue
                res += [(quant, apply_qty)]
                quantity -= apply_qty
                if float_is_zero(quantity, precision_rounding=rounding):
                    break

            offset += 10
        return res
Exemple #5
0
 def _compute_invoice_status(self):
     """
     Compute the invoice status of a SO line. Possible statuses:
     - no: if the SO is not in status 'sale' or 'done', we consider that there is nothing to
       invoice. This is also hte default value if the conditions of no other status is met.
     - to invoice: we refer to the quantity to invoice of the line. Refer to method
       `_get_to_invoice_qty()` for more information on how this quantity is calculated.
     - upselling: this is possible only for a product invoiced on ordered quantities for which
       we delivered more than expected. The could arise if, for example, a project took more
       time than expected but we decided not to invoice the extra cost to the client. This
       occurs onyl in state 'sale', so that when a SO is set to done, the upselling opportunity
       is removed from the list.
     - invoiced: the quantity invoiced is larger or equal to the quantity ordered.
     """
     precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
     for line in self:
         if line.state not in ('sale', 'done'):
             line.invoice_status = 'no'
         elif not float_is_zero(line.qty_to_invoice, precision_digits=precision):
             line.invoice_status = 'to invoice'
         elif line.state == 'sale' and line.product_id.invoice_policy == 'order' and\
                 float_compare(line.qty_delivered, line.product_uom_qty, precision_digits=precision) == 1:
             line.invoice_status = 'upselling'
         elif float_compare(line.qty_invoiced, line.product_uom_qty, precision_digits=precision) >= 0:
             line.invoice_status = 'invoiced'
         else:
             line.invoice_status = 'no'
Exemple #6
0
 def _resolve_inventory_line(self,  inventory_line):  
     if inventory_line.product_id.cost_method == 'real':
         price = inventory_line.get_price( )           
         product_qty = inventory_line.product_qty
         
        
         if not float_is_zero(abs(inventory_line.standard_price - price), precision_digits=2 ): 
             
             line_price = inventory_line.standard_price
             inventory_line.write( {'standard_price': price, 'product_qty':0.0 } )
             inventory_line.product_id.write({'standard_price':price} )
             move_id = super(stock_inventory_line,self)._resolve_inventory_line(    inventory_line )
             if move_id:
                 move = self.env['stock.move'].browse(move_id)
                 move.action_done()
             inventory_line.write( {'standard_price': line_price, 'product_qty':product_qty + inventory_line.theoretical_qty } )
             
         inventory_line.product_id.write( {'standard_price':inventory_line.standard_price}  ) 
         move_id = super(stock_inventory_line,self)._resolve_inventory_line(    inventory_line )
         if   product_qty <> inventory_line.product_qty:
             inventory_line.write( {'product_qty':product_qty } )
         if move_id:
             move = self.env['stock.move'].browse(move_id)
             move.action_done()
     return move_id
 def compute_full_after_batch_reconcile(self):
     aml_id, partial_rec_id = super(AccountMoveLine, self).compute_full_after_batch_reconcile()
     #check if the reconcilation is full
     partial_rec_set = self.env['account.partial.reconcile']
     total_debit = 0
     total_credit = 0
     total_amount_currency = 0
     currency = False
     # If we have an exchange rate entry, add it's value to amount_currency
     if aml_id and partial_rec_id:
         exchange_rate_aml = self.browse([aml_id])
         exchange_rate_partial_rec = self.env['account.partial.reconcile'].browse([partial_rec_id])
         total_amount_currency += exchange_rate_aml.amount_currency
         partial_rec_set |= exchange_rate_partial_rec
     for aml in self:
         total_debit += aml.debit
         total_credit += aml.credit
         if not currency and aml.currency_id:
             currency = aml.currency_id
         if aml.currency_id and aml.currency_id == currency:
             total_amount_currency += aml.amount_currency
         partial_rec_set |= aml.matched_debit_ids | aml.matched_credit_ids
     partial_rec_ids = [x.id for x in list(partial_rec_set)]
     #if the total debit and credit are equal, and the total amount in currency is 0, the reconciliation is full
     digits_rounding_precision = self[0].company_id.currency_id.rounding
     if float_compare(total_debit, total_credit, precision_rounding=digits_rounding_precision) == 0 \
       and (not currency or float_is_zero(total_amount_currency, precision_rounding=currency.rounding)):
         #in that case, mark the reference on the partial reconciliations and the entries
         self.env['account.full.reconcile'].with_context(check_move_validity=False).create({
             'partial_reconcile_ids': [(4, p_id) for p_id in partial_rec_ids],
             'reconciled_line_ids': [(4, r_id) for r_id in ((self + exchange_rate_aml).ids if aml_id else self.ids)],
         })
    def _compute_residual(self):
        fp_company = self.env['account.fiscal.position'].search(
            [('id', '=', self.company_id.partner_id.property_account_position_id.id)])
        company_tax_ids = [base_tax.tax_id.id for base_tax in fp_company.tax_ids_invoice]

        residual = 0.0
        residual_company_signed = 0.0
        sign = self.type in ['in_refund', 'out_refund'] and -1 or 1
        for line in self.sudo().move_id.line_ids:
            if line.tax_line_id.id not in company_tax_ids:
                if line.account_id.internal_type in ('receivable', 'payable'):
                    residual_company_signed += line.amount_residual
                    if line.currency_id == self.currency_id:
                        residual += line.amount_residual_currency if line.currency_id else line.amount_residual
                    else:
                        from_currency = (line.currency_id and line.currency_id.with_context(date=line.date)) or line.company_id.currency_id.with_context(date=line.date)
                        residual += from_currency.compute(line.amount_residual, self.currency_id)
        self.residual_company_signed = abs(residual_company_signed) * sign
        self.residual_signed = abs(residual) * sign
        self.residual = abs(residual)
        digits_rounding_precision = self.currency_id.rounding
        if float_is_zero(self.residual, precision_rounding=digits_rounding_precision):
            self.reconciled = True
        else:
            self.reconciled = False
Exemple #9
0
    def _resolve_inventory_line(self,  inventory_line):  

        product_qty = inventory_line.product_qty
        if inventory_line.product_id.cost_method == 'real':
            price = inventory_line.get_price( )           
      
            if not float_is_zero(abs(inventory_line.standard_price - price), precision_digits=2 ): 
                # se completeaza o line de inventar cu cantitate zero si cu vechiul pret
                line_price = inventory_line.standard_price
                inventory_line.write( {'standard_price': price, 'product_qty':0.0 } )
                inventory_line.product_id.write({'standard_price':price} )
                move_id = super(stock_inventory_line,self)._resolve_inventory_line(    inventory_line )

                inventory_line.write( {'standard_price': line_price, 'product_qty':product_qty + inventory_line.theoretical_qty } )
                
            inventory_line.product_id.write( {'standard_price':inventory_line.standard_price}  ) # acutlizare pret in produs
            
        move_id = super(stock_inventory_line,self)._resolve_inventory_line(    inventory_line )
        if   product_qty <> inventory_line.product_qty:
            inventory_line.write( {'product_qty':product_qty } )
        if move_id:
            move = self.env['stock.move'].browse(move_id)
            move.action_done()
                
        return move_id
    def action_produce(self, production_id, production_qty, production_mode,
                       wiz=False):
        if production_mode == 'only_produce':
            production = self.browse(production_id)
            prod_name = production.name
            procurement_group = self.env['procurement.group'].search(
                [('name', '=', prod_name)], limit=1)
            if not procurement_group:
                procurement_group = self.env['procurement.group'].create(
                    {'name': prod_name})
            self = self.with_context(set_push_group=procurement_group.id)
            # Volvemos a hacer browse para que use el context correcto
            production = self.browse(production_id)
            precision = self.env['decimal.precision'].precision_get(
                'Product Unit of Measure')
            production_qty_uom = self.env['product.uom']._compute_qty(
                production.product_uom.id, production_qty,
                production.product_id.uom_id.id)
            # To produce remaining qty of final product
            produced_products = {}
            for produced_product in production.move_created_ids2:
                if produced_product.scrapped:
                    continue
                if not produced_products.get(produced_product.product_id.id,
                                             False):
                    produced_products[produced_product.product_id.id] = 0
                produced_products[produced_product.product_id.id] += \
                    produced_product.product_qty
            for produce_product in production.move_created_ids:
                subproduct_factor = production._get_subproduct_factor(
                    produce_product.id)
                lot_id = False
                if wiz:
                    lot_id = wiz.lot_id.id
                qty = min(subproduct_factor * production_qty_uom,
                          produce_product.product_qty)
                new_moves = produce_product.action_consume(
                    qty, location_id=produce_product.location_id.id,
                    restrict_lot_id=lot_id)
                new_moves = self.env['stock.move'].browse(new_moves)
                new_moves.write({'production_id': production_id})
                remaining_qty = subproduct_factor * production_qty_uom - qty
                if not float_is_zero(remaining_qty,
                                     precision_digits=precision):
                    extra_move = produce_product.copy(
                        default={'product_uom_qty': remaining_qty,
                                 'production_id': production_id})
                    # Cancelamos disponibilidad de albaranes ya creados
                    # Para que asigne con el nuevo movimiento
                    pickings = (production.move_created_ids +
                                production.move_created_ids2).mapped(
                                    'move_dest_id.picking_id').filtered(
                                        lambda r: r.state == 'assigned')
                    pickings.do_unreserve()
                    extra_move.action_confirm()
                    pickings.rereserve_pick()
                    extra_move.action_done()

        return super(MrpProduction, self).action_produce(
            production_id, production_qty, production_mode, wiz)
    def create(self, vals):
        res = super(AccountPartialReconcile, self).create(vals)
        #check if the reconcilation is full
        #first, gather all journal items involved in the reconciliation just created
        partial_rec_set = OrderedDict.fromkeys([x for x in res])
        aml_set = self.env['account.move.line']
        total_debit = 0
        total_credit = 0
        total_amount_currency = 0
        currency = None
        for partial_rec in partial_rec_set:
            if currency is None:
                currency = partial_rec.currency_id
            for aml in [partial_rec.debit_move_id, partial_rec.credit_move_id]:
                if aml not in aml_set:
                    total_debit += aml.debit
                    total_credit += aml.credit
                    aml_set |= aml
                    if aml.currency_id and aml.currency_id == currency:
                        total_amount_currency += aml.amount_currency
                for x in aml.matched_debit_ids | aml.matched_credit_ids:
                    partial_rec_set[x] = None
        partial_rec_ids = [x.id for x in partial_rec_set.keys()]
        aml_ids = [x.id for x in aml_set]
        #then, if the total debit and credit are equal, or the total amount in currency is 0, the reconciliation is full
        digits_rounding_precision = aml_set[0].company_id.currency_id.rounding
        if float_compare(total_debit, total_credit, precision_rounding=digits_rounding_precision) == 0 \
          or (currency and float_is_zero(total_amount_currency, precision_rounding=currency.rounding)):

            #in that case, mark the reference on the partial reconciliations and the entries
            self.env['account.full.reconcile'].with_context(check_move_validity=False).create({
                'partial_reconcile_ids': [(6, 0, partial_rec_ids)],
                'reconciled_line_ids': [(6, 0, aml_ids)]})
        return res
 def compute_full_after_batch_reconcile(self):
     super(AccountMoveLine, self).compute_full_after_batch_reconcile()
     #check if the reconcilation is full
     partial_rec_set = self.env['account.partial.reconcile']
     total_debit = 0
     total_credit = 0
     total_amount_currency = 0
     currency = False
     for aml in self:
         total_debit += aml.debit
         total_credit += aml.credit
         if not currency and aml.currency_id:
             currency = aml.currency_id
         if aml.currency_id and aml.currency_id == currency:
             total_amount_currency += aml.amount_currency
             partial_rec_set |= aml.matched_debit_ids | aml.matched_credit_ids
     partial_rec_ids = [x.id for x in list(partial_rec_set)]
     #if the total debit and credit are equal, and the total amount in currency is 0, the reconciliation is full
     digits_rounding_precision = self[0].company_id.currency_id.rounding
     if float_compare(total_debit, total_credit, precision_rounding=digits_rounding_precision) == 0 \
       and (not currency or float_is_zero(total_amount_currency, precision_rounding=currency.rounding)):
         #in that case, mark the reference on the partial reconciliations and the entries
         self.env['account.full.reconcile'].with_context(check_move_validity=False).create({
             'partial_reconcile_ids': [(6, 0, partial_rec_ids)],
             'reconciled_line_ids': [(6, 0, self.ids)]})
Exemple #13
0
    def compute_depreciation_board(self):
        self.ensure_one()

        posted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: x.move_check).sorted(key=lambda l: l.depreciation_date)
        unposted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: not x.move_check)

        # Remove old unposted depreciation lines. We cannot use unlink() with One2many field
        commands = [(2, line_id.id, False) for line_id in unposted_depreciation_line_ids]

        if self.value_residual != 0.0:
            amount_to_depr = residual_amount = self.value_residual
            if self.prorata:
                depreciation_date = datetime.strptime(self._get_last_depreciation_date()[self.id], DF).date()
            else:
                # depreciation_date = 1st of January of purchase year if annual valuation, 1st of
                # purchase month in other cases
                if self.method_period >= 12:
                    asset_date = datetime.strptime(self.date[:4] + '-01-01', DF).date()
                else:
                    asset_date = datetime.strptime(self.date[:7] + '-01', DF).date()
                # if we already have some previous validated entries, starting date isn't 1st January but last entry + method period
                if posted_depreciation_line_ids and posted_depreciation_line_ids[-1].depreciation_date:
                    last_depreciation_date = datetime.strptime(posted_depreciation_line_ids[-1].depreciation_date, DF).date()
                    depreciation_date = last_depreciation_date + relativedelta(months=+self.method_period)
                else:
                    depreciation_date = asset_date
            day = depreciation_date.day
            month = depreciation_date.month
            year = depreciation_date.year
            total_days = (year % 4) and 365 or 366

            undone_dotation_number = self._compute_board_undone_dotation_nb(depreciation_date, total_days)

            for x in range(len(posted_depreciation_line_ids), undone_dotation_number):
                sequence = x + 1
                amount = self._compute_board_amount(sequence, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date)
                amount = self.currency_id.round(amount)
                if float_is_zero(amount, precision_rounding=self.currency_id.rounding):
                    continue
                residual_amount -= amount
                vals = {
                    'amount': amount,
                    'asset_id': self.id,
                    'sequence': sequence,
                    'name': (self.code or '') + '/' + str(sequence),
                    'remaining_value': residual_amount,
                    'depreciated_value': self.value - (self.salvage_value + residual_amount),
                    'depreciation_date': depreciation_date.strftime(DF),
                }
                commands.append((0, False, vals))
                # Considering Depr. Period as months
                depreciation_date = date(year, month, day) + relativedelta(months=+self.method_period)
                day = depreciation_date.day
                month = depreciation_date.month
                year = depreciation_date.year

        self.write({'depreciation_line_ids': commands})

        return True
    def action_produce(self, cr, uid, production_id, production_qty, production_mode, wiz=False, context=None):
        if context is None:
            context = {}
        context = dict(context)
        stock_mov_obj = self.pool.get('stock.move')
        uom_obj = self.pool.get("product.uom")
        production = self.browse(cr, uid, production_id, context=context)
        production_qty_uom = uom_obj._compute_qty(cr, uid, production.product_uom.id, production_qty, production.product_id.uom_id.id)
        precision = self.pool['decimal.precision'].precision_get(cr, uid, 'Product Unit of Measure')

        main_production_move = False
        if production_mode == 'produce':  # New Case: Produce Only
            produced_products = {}
            for produced_product in production.move_created_ids2:
                if produced_product.scrapped:
                    continue
                if not produced_products.get(produced_product.product_id.id, False):
                    produced_products[produced_product.product_id.id] = 0
                produced_products[produced_product.product_id.id] += produced_product.product_qty

            for produce_product in production.move_created_ids:
                subproduct_factor = self._get_subproduct_factor(cr, uid, production.id, produce_product.id, context=context)
                lot_id = False
                if wiz:
                    lot_id = wiz.lot_id.id
                qty = min(subproduct_factor * production_qty_uom, produce_product.product_qty) #Needed when producing more than maximum quantity
                new_moves = stock_mov_obj.action_consume(cr, uid, [produce_product.id], qty,
                                                         location_id=produce_product.location_id.id, restrict_lot_id=lot_id, context=context)
                stock_mov_obj.write(cr, uid, new_moves, {'production_id': production_id}, context=context)
                remaining_qty = subproduct_factor * production_qty_uom - qty
                if not float_is_zero(remaining_qty, precision_digits=precision):
                    # In case you need to make more than planned
                    # consumed more in wizard than previously planned
                    extra_move_id = stock_mov_obj.copy(cr, uid, produce_product.id, default={'product_uom_qty': remaining_qty,
                                                                                             'production_id': production_id}, context=context)
                    stock_mov_obj.action_confirm(cr, uid, [extra_move_id], context=context)
                    stock_mov_obj.action_done(cr, uid, [extra_move_id], context=context)

                if produce_product.product_id.id == production.product_id.id:
                    main_production_move = produce_product.id

            if not production.move_created_ids and \
                not (context.get('default_mode', False) and context['default_mode'] == 'consume'):
                self.signal_workflow(cr, uid, [production_id], 'button_finished_validated')
        else:
            if not main_production_move:
                main_production_move = production.move_created_ids2 and production.move_created_ids2[0].id
            context.update({'main_production_move': main_production_move})  # Para escribirlo en el write y en el action_consume()
            res = super(mrp_production, self).action_produce(cr, uid, production_id, production_qty, production_mode, wiz=wiz, context=context)
            if not production.move_created_ids and \
                not (context.get('default_mode', False) and context['default_mode'] == 'consume'):
                self.signal_workflow(cr, uid, [production_id], 'button_finished_validated')
            if context.get('default_mode', False) and context['default_mode'] == 'consume':  # Custom behaivor, set closed state
                self.signal_workflow(cr, uid, [production_id], 'button_validated_closed')

        return True
    def is_zero(self, amount):
        """ Return true if `amount` is small enough to be treated as zero
            according to currency `self`'s rounding rules.

            Warning: ``is_zero(amount1-amount2)`` is not always equivalent to 
            ``compare_amounts(amount1,amount2) == 0``, as the former will round
            after computing the difference, while the latter will round before,
            giving different results, e.g., 0.006 and 0.002 at 2 digits precision.
        """
        return float_is_zero(amount, precision_rounding=self.rounding)
    def is_zero(self, cr, uid, currency, amount):
        """Returns true if ``amount`` is small enough to be treated as
           zero according to ``currency``'s rounding rules.

           Warning: ``is_zero(amount1-amount2)`` is not always equivalent to 
           ``compare_amounts(amount1,amount2) == 0``, as the former will round after
           computing the difference, while the latter will round before, giving
           different results for e.g. 0.006 and 0.002 at 2 digits precision.

           :param Record currency: currency for which we are rounding
           :param float amount: amount to compare with currency's zero
        """
        return float_is_zero(amount, precision_rounding=currency.rounding)
Exemple #17
0
    def invoice_line_create(self, invoice_id, qty):
        """
        Create an invoice line. The quantity to invoice can be positive (invoice) or negative
        (refund).

        :param invoice_id: integer
        :param qty: float quantity to invoice
        """
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        for line in self:
            if not float_is_zero(qty, precision_digits=precision):
                vals = line._prepare_invoice_line(qty=qty)
                vals.update({'invoice_id': invoice_id, 'sale_line_ids': [(6, 0, [line.id])]})
                self.env['account.invoice.line'].create(vals)
Exemple #18
0
 def _get_progress(self):
     if self.ids:
         self.env.cr.execute("SELECT task_id, COALESCE(SUM(hours),0) FROM project_task_work WHERE task_id IN %s GROUP BY task_id",(tuple(self.ids),))
         hours = dict(self.env.cr.fetchall())
         for task in self:   
             task.effective_hours =  hours.get(task.id, 0.0)
             task.total_hours =  (task.remaining_hours or 0.0) + hours.get(task.id, 0.0)    
             task.delay_hours = task.total_hours - task.planned_hours
             task.progress = 0.0
                       
             if not float_is_zero(task.total_hours, precision_digits=2):
                 task.progress = round(min(100.0 * hours.get(task.id, 0.0) / task.total_hours, 99.99),2)
             if task.stage_id and  task.stage_id.use_progress:
                 task.progress = task.stage_id.progress
Exemple #19
0
 def calc_price_percent(self):
     self.ensure_one()
     domain  = eval( self.product_id.percent_domain )
     domain.extend([('order_id','=',self.order_id.id),('id','!=',self.id)])
     
     lines = self.env['sale.order.line'].search(domain)
     total_amount = 0
     for line in lines:
         total_amount += line.price_subtotal
         
     total_amount =  total_amount / 100 
     
     if not float_is_zero(self.price_unit -  total_amount, precision_digits=2): 
         self.write({'price_unit':total_amount})
Exemple #20
0
 def _compute_invoice_status(self):
     precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
     for line in self:
         if line.state not in ('sale', 'done'):
             line.invoice_status = 'no'
         elif not float_is_zero(line.qty_to_invoice, precision_digits=precision):
             line.invoice_status = 'to invoice'
         elif float_compare(line.qty_invoiced, line.product_uom_qty, precision_digits=precision) == 1 or\
                 float_compare(line.qty_invoiced, line.product_uom_qty, precision_digits=precision) >= 0 and\
                 float_compare(line.qty_delivered, line.product_uom_qty, precision_digits=precision) == 1:
             line.invoice_status = 'upselling'
         elif float_compare(line.qty_invoiced, line.product_uom_qty, precision_digits=precision) == 0:
             line.invoice_status = 'invoiced'
         else:
             line.invoice_status = 'no'
    def test_timesheet_delivery(self):
        """ Test timesheet invoicing with 'invoice on delivery' timetracked products """
        inv_obj = self.env['account.invoice']
        # intial so
        prod_ts = self.env.ref('product.product_product_2')
        so_vals = {
            'partner_id': self.partner.id,
            'partner_invoice_id': self.partner.id,
            'partner_shipping_id': self.partner.id,
            'order_line': [(0, 0, {'name': prod_ts.name, 'product_id': prod_ts.id, 'product_uom_qty': 50, 'product_uom': prod_ts.uom_id.id, 'price_unit': prod_ts.list_price})],
            'pricelist_id': self.env.ref('product.list0').id,
        }
        so = self.env['sale.order'].create(so_vals)
        so.action_confirm()
        self.assertEqual(so.invoice_status, 'no', 'Sale Timesheet: "invoice on delivery" should not need to be invoiced on so confirmation')
        # let's log some timesheets
        self.env['account.analytic.line'].create({
            'name': 'Test Line',
            'account_id': so.project_id.id,
            'unit_amount': 10.5,
            'user_id': self.manager.id,
            'is_timesheet': True,
        })
        self.assertEqual(so.invoice_status, 'to invoice', 'Sale Timesheet: "invoice on delivery" timesheets should set the so in "to invoice" status when logged')
        inv_id = so.action_invoice_create()
        inv = inv_obj.browse(inv_id)
        self.assertTrue(float_is_zero(inv.amount_total - so.order_line.price_unit * 10.5, precision_digits=2), 'Sale: invoice generation on timesheets product is wrong')

        self.env['account.analytic.line'].create({
            'name': 'Test Line',
            'account_id': so.project_id.id,
            'unit_amount': 39.5,
            'user_id': self.user.id,
            'is_timesheet': True,
        })
        self.assertEqual(so.invoice_status, 'to invoice', 'Sale Timesheet: "invoice on delivery" timesheets should not modify the invoice_status of the so')
        so.action_invoice_create()
        self.assertEqual(so.invoice_status, 'invoiced', 'Sale Timesheet: "invoice on delivery" timesheets should be invoiced completely by now')

        self.env['account.analytic.line'].create({
            'name': 'Test Line',
            'account_id': so.project_id.id,
            'unit_amount': 10,
            'user_id': self.user.id,
            'is_timesheet': True,
        })
        self.assertEqual(so.invoice_status, 'to invoice', 'Sale Timesheet: supplementary timesheets do not change the status of the SO')
    def _create_standard_deviation_entries(self, line, move_id, acc_prod=None):
        """
        Create standard deviation journal items based on predefined product
        account valuation, gain and loss company's accounts
        """
        if float_is_zero(
                line.additional_landed_cost,
                self.pool.get('decimal.precision').precision_get(
                    self._cr, self._uid, 'Account')):
            return False

        valuation_account_id, gain_account_id, loss_account_id = \
            self._get_deviation_accounts(line.product_id.id, acc_prod)

        return self._create_standard_deviation_entry_lines(
            line, move_id, valuation_account_id, gain_account_id,
            loss_account_id)
    def _process_order(self, cr, uid, order, context=None):
        session = self.pool.get('pos.session').browse(cr, uid, order['pos_session_id'], context=context)

        if session.state == 'closing_control' or session.state == 'closed':
            session_id = self._get_valid_session(cr, uid, order, context=context)
            session = self.pool.get('pos.session').browse(cr, uid, session_id, context=context)
            order['pos_session_id'] = session_id

        order_id = self.create(cr, uid, self._order_fields(cr, uid, order, context=context),context)
        journal_ids = set()
        for payments in order['statement_ids']:
            self.add_payment(cr, uid, order_id, self._payment_fields(cr, uid, payments[2], context=context), context=context)
            journal_ids.add(payments[2]['journal_id'])

        if session.sequence_number <= order['sequence_number']:
            session.write({'sequence_number': order['sequence_number'] + 1})
            session.refresh()

        if not float_is_zero(order['amount_return'], self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')):
            # cash_journal = session.cash_journal_id.id
            cash_journal = False
            if session.config_id.journal_negativo_id:
                cash_journal =  session.config_id.journal_negativo_id.id
            if not cash_journal:
                # Select for change one of the cash journals used in this payment
                cash_journal_ids = self.pool['account.journal'].search(cr, uid, [
                    ('type', '=', 'cash'),
                    ('id', 'in', list(journal_ids)),
                ], limit=1, context=context)
                if not cash_journal_ids:
                    # If none, select for change one of the cash journals of the POS
                    # This is used for example when a customer pays by credit card
                    # an amount higher than total amount of the order and gets cash back
                    cash_journal_ids = [statement.journal_id.id for statement in session.statement_ids
                                        if statement.journal_id.type == 'cash']
                    if not cash_journal_ids:
                        raise osv.except_osv( _('error!'),
                            _("No cash statement found for this session. Unable to record returned cash."))
                cash_journal = cash_journal_ids[0]
            self.add_payment(cr, uid, order_id, {
                'amount': -order['amount_return'],
                'payment_date': time.strftime('%Y-%m-%d %H:%M:%S'),
                'payment_name': _('return'),
                'journal': cash_journal,
            }, context=context)
        return order_id
    def _prepare_reconciliation_move_line(self, move, amount):
        """ Prepare the dict of values to create the move line from a statement line.

            :param recordset move: the account.move to link the move line
            :param float amount: the amount of transaction that wasn't already reconciled
        """
        company_currency = self.journal_id.company_id.currency_id
        statement_currency = self.journal_id.currency_id or company_currency
        st_line_currency = self.currency_id or statement_currency

        amount_currency = False
        if statement_currency != company_currency or st_line_currency != company_currency:
            # First get the ratio total mount / amount not already reconciled
            if statement_currency == company_currency:
                total_amount = self.amount
            elif st_line_currency == company_currency:
                total_amount = self.amount_currency
            else:
                total_amount = statement_currency.with_context({'date': self.date}).compute(self.amount, company_currency, round=False)
            if float_is_zero(total_amount - amount, precision_rounding=company_currency.rounding):
                ratio = total_amount / amount
            else:
                ratio = 1.0
            # Then use it to adjust the statement.line field that correspond to the move.line amount_currency
            if statement_currency != company_currency:
                amount_currency = self.amount * ratio
            elif st_line_currency != company_currency:
                amount_currency = self.amount_currency * ratio
        return {
            'name': self.name,
            'date': self.date,
            'ref': self.ref,
            'move_id': move.id,
            'partner_id': self.partner_id and self.partner_id.id or False,
            'account_id': amount >= 0 \
                and self.statement_id.journal_id.default_credit_account_id.id \
                or self.statement_id.journal_id.default_debit_account_id.id,
            'credit': amount < 0 and -amount or 0.0,
            'debit': amount > 0 and amount or 0.0,
            'statement_id': self.statement_id.id,
            'journal_id': self.statement_id.journal_id.id,
            'currency_id': statement_currency != company_currency and statement_currency.id or (st_line_currency != company_currency and st_line_currency.id or False),
            'amount_currency': amount_currency,
        }
Exemple #25
0
 def _compute_residual(self):
     residual = 0.0
     residual_signed = 0.0
     residual_company_signed = 0.0
     sign = self.type in ['in_refund', 'in_invoice'] and -1 or 1
     for line in self.sudo().move_id.line_ids:
         if line.account_id.internal_type in ('receivable', 'payable'):
             residual_company_signed += line.amount_residual * sign
             if line.currency_id == self.currency_id:
                 residual += line.amount_residual_currency if line.currency_id else line.amount_residual
             else:
                 from_currency = (line.currency_id and line.currency_id.with_context(date=line.date)) or line.company_id.currency_id.with_context(date=line.date)
                 residual += from_currency.compute(line.amount_residual, self.currency_id)
     self.residual_company_signed = residual_company_signed
     self.residual_signed = abs(residual) * sign
     self.residual = abs(residual)
     digits_rounding_precision = self.currency_id.rounding
     if float_is_zero(self.residual, digits_rounding_precision):
         self.reconciled = True
Exemple #26
0
    def action_invoice_create(self, grouped=False, final=False):
        """
        Create the invoice associated to the SO.
        :param grouped: if True, invoices are grouped by SO id. If False, invoices are grouped by
                        (partner, currency)
        :param final: if True, refunds will be generated if necessary
        :returns: list of created invoices
        """
        inv_obj = self.env['account.invoice']
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        invoices = {}

        for order in self:
            group_key = order.id if grouped else (order.partner_id.id, order.currency_id.id)
            for line in order.order_line.sorted(key=lambda l: l.qty_to_invoice < 0):
                if float_is_zero(line.qty_to_invoice, precision_digits=precision):
                    continue
                if group_key not in invoices:
                    inv_data = order._prepare_invoice()
                    invoice = inv_obj.create(inv_data)
                    invoices[group_key] = invoice
                elif group_key in invoices and order.name not in invoices[group_key].origin.split(', '):
                    invoices[group_key].write({'origin': invoices[group_key].origin + ', ' + order.name})
                if line.qty_to_invoice > 0:
                    line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice)
                elif line.qty_to_invoice < 0 and final:
                    line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice)

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

        return [inv.id for inv in invoices.values()]
Exemple #27
0
    def _process_mobility_order(self, cr, uid, order, context=None):
                
        if 'name' not in order or order['name'] is False:
            order['name'] = "/"                
        if 'partner_id' not in order:
            order['partner_id'] = False
        if 'pos_session_id' not in order:
            session = super(pos_order, self)._default_session(cr, uid, context=context)
            if session is False:
                raise osv.except_osv( _('Error!'), _("POS order is not attached to an opened session."))
            order['pos_session_id'] = session
        
        session = self.pool.get('pos.session').browse(cr, uid, order['pos_session_id'], context=context)  
        # Create new order
        order_id = self.create(cr, uid, self._order_fields(cr, uid, order, context=context), context)
        
        for payments in order['statement_ids']:
            if ('statement_id' not in payments[2]):
                payments[2]['statement_id'] = False
            self.add_payment(cr, uid, order_id, self._payment_fields(cr, uid, payments[2], context=context), context=context)
            
        # Get order created
        order_row = self.browse(cr, uid, order_id, context=context)
        order['amount_return'] = abs(order_row['amount_total'] - order_row['amount_paid'])
        
        if not float_is_zero(order['amount_return'], self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')):
            cash_journal = session.cash_journal_id
            if not cash_journal:
                cash_journal_ids = filter(lambda st: st.journal_id.type=='cash', session.statement_ids)
                if not len(cash_journal_ids):
                    raise osv.except_osv( _('error!'),
                        _("No cash statement found for this session. Unable to record returned cash."))
                cash_journal = cash_journal_ids[0].journal_id
            self.add_payment(cr, uid, order_id, {
                'amount': -order['amount_return'],
                'payment_date': time.strftime('%Y-%m-%d %H:%M:%S'),
                'payment_name': _('return'),
                'journal': cash_journal.id,
            }, context=context)

        return order_id
    def _process_order(self, cr, uid, order, context=None):
        product_obj = self.pool.get('product.product')
        line_obj = self.pool.get('pos.order.line')
        order_id = self.create(cr, uid, self._order_fields(cr, uid, order, context=context),context)

        for payments in order['statement_ids']:
            self.add_payment(cr, uid, order_id, self._payment_fields(cr, uid, payments[2], context=context), context=context)
        if order.get('disc_checked',False): 
            prod_ids = product_obj.search(cr, uid, [('default_code','=','disc_fix')])
            if prod_ids:
                pid = prod_ids[0]
            else:
                pid = product_obj.create(cr, uid, {'name': 'Discount Fixed Price', 'default_code' : 'disc_fix', 'type': 'service'})
            line_vals = {
                'product_id' : pid,
                'qty' : 1,
                'price_unit' : -(order.get('disc_amount',False)),
                'order_id' : order_id
            }
            line_obj.create(cr, uid, line_vals)
            
        session = self.pool.get('pos.session').browse(cr, uid, order['pos_session_id'], context=context)
        if session.sequence_number <= order['sequence_number']:
            session.write({'sequence_number': order['sequence_number'] + 1})
            session.refresh()

        if not float_is_zero(order['amount_return'], self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')):
            cash_journal = session.cash_journal_id
            if not cash_journal:
                cash_journal_ids = filter(lambda st: st.journal_id.type=='cash', session.statement_ids)
                if not len(cash_journal_ids):
                    raise osv.except_osv( _('error!'),
                        _("No cash statement found for this session. Unable to record returned cash."))
                cash_journal = cash_journal_ids[0].journal_id
            self.add_payment(cr, uid, order_id, {
                'amount': -order['amount_return'],
                'payment_date': time.strftime('%Y-%m-%d %H:%M:%S'),
                'payment_name': _('return'),
                'journal': cash_journal.id,
            }, context=context)
        return order_id
    def _create_deviation_accounting_entries(
            self, move_id, product_id, old_avg, new_avg, qty, acc_prod=None):
        '''
        This method takes the variation in value for average and books it as
        Inventory Valuation Deviation
        '''
        amount = (old_avg - new_avg) * qty
        if float_is_zero(
                amount,
                self.pool.get('decimal.precision').precision_get(
                    self._cr, self._uid, 'Account')):
            return False

        valuation_account_id, gain_account_id, loss_account_id = \
            self._get_deviation_accounts(product_id, acc_prod)

        product_brw = self.env['product.product'].browse(product_id)

        return self._create_deviation_account_move_line(
            move_id, gain_account_id, loss_account_id,
            valuation_account_id, amount, product_brw)
Exemple #30
0
 def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None):
     res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context)
     if inv_type in ('out_invoice', 'out_refund') and move.procurement_id and move.procurement_id.sale_line_id:
         sale_line = move.procurement_id.sale_line_id
         res['invoice_line_tax_id'] = [(6, 0, [x.id for x in sale_line.tax_id])]
         res['account_analytic_id'] = sale_line.order_id.project_id and sale_line.order_id.project_id.id or False
         res['discount'] = sale_line.discount
         if move.product_id.id != sale_line.product_id.id:
             precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Discount')
             if float_is_zero(sale_line.discount, precision_digits=precision):
                 res['price_unit'] = self.pool['product.pricelist'].price_get(
                     cr, uid, [sale_line.order_id.pricelist_id.id],
                     move.product_id.id, move.product_uom_qty or 1.0,
                     sale_line.order_id.partner_id, context=context)[sale_line.order_id.pricelist_id.id]
             else:
                 res['price_unit'] = move.product_id.lst_price
         else:
             res['price_unit'] = sale_line.price_unit
         uos_coeff = move.product_uom_qty and move.product_uos_qty / move.product_uom_qty or 1.0
         res['price_unit'] = res['price_unit'] / uos_coeff
     return res
Exemple #31
0
    def process_bank_reconciliation(self,
                                    cr,
                                    uid,
                                    id,
                                    mv_line_dicts,
                                    context=None):
        """ Creates a move line for each item of mv_line_dicts and for the statement line. Reconcile a new move line with its counterpart_move_line_id if specified. Finally, mark the statement line as reconciled by putting the newly created move id in the column journal_entry_id.

            :param int id: id of the bank statement line
            :param list of dicts mv_line_dicts: move lines to create. If counterpart_move_line_id is specified, reconcile with it
        """
        if context is None:
            context = {}
        st_line = self.browse(cr, uid, id, context=context)
        company_currency = st_line.journal_id.company_id.currency_id
        statement_currency = st_line.journal_id.currency or company_currency
        bs_obj = self.pool.get('account.bank.statement')
        am_obj = self.pool.get('account.move')
        aml_obj = self.pool.get('account.move.line')
        currency_obj = self.pool.get('res.currency')

        # Checks
        if st_line.bank_reconcile_id.id:
            raise osv.except_osv(
                _('Error!'),
                _('The bank statement line was already reconciled.'))
        for mv_line_dict in mv_line_dicts:
            for field in ['debit', 'credit', 'amount_currency']:
                if field not in mv_line_dict:
                    mv_line_dict[field] = 0.0
            if mv_line_dict.get('counterpart_move_line_id'):
                mv_line = aml_obj.browse(
                    cr,
                    uid,
                    mv_line_dict.get('counterpart_move_line_id'),
                    context=context)
                if mv_line.bank_reconcile_id:
                    raise osv.except_osv(
                        _('Error!'),
                        _('A selected move line was already reconciled.'))

        bank_reconcile_obj = self.pool.get('account.bank.statement.reconcile')
        bank_reconcile_name = (st_line.statement_id.name
                               or st_line.name) + "/" + str(st_line.sequence)
        bank_reconcile_id = bank_reconcile_obj.create(
            cr, uid, {'name': bank_reconcile_name})
        st_line.write({'bank_reconcile_id': bank_reconcile_id})

        move_created = False

        for mv_line_dict in mv_line_dicts:
            for field in ['debit', 'credit', 'amount_currency']:
                if field not in mv_line_dict:
                    mv_line_dict[field] = 0.0
            if mv_line_dict.get('counterpart_move_line_id'):
                mv_line = aml_obj.browse(
                    cr,
                    uid,
                    mv_line_dict.get('counterpart_move_line_id'),
                    context=context)
                mv_line.write({'bank_reconcile_id': bank_reconcile_id})
                move_created = True

        if not move_created:
            # Create the move
            move_name = (st_line.statement_id.name
                         or st_line.name) + "/" + str(st_line.sequence)
            move_vals = bs_obj._prepare_move(cr,
                                             uid,
                                             st_line,
                                             move_name,
                                             context=context)
            move_id = am_obj.create(cr, uid, move_vals, context=context)

            # Create the move line for the statement line
            if st_line.statement_id.currency.id != company_currency.id:
                if st_line.currency_id == company_currency:
                    amount = st_line.amount_currency
                else:
                    ctx = context.copy()
                    ctx['date'] = st_line.date
                    amount = currency_obj.compute(
                        cr,
                        uid,
                        st_line.statement_id.currency.id,
                        company_currency.id,
                        st_line.amount,
                        context=ctx)
            else:
                amount = st_line.amount
            bank_st_move_vals = bs_obj._prepare_bank_move_line(
                cr,
                uid,
                st_line,
                move_id,
                amount,
                company_currency.id,
                context=context)
            aml_obj.create(cr, uid, bank_st_move_vals, context=context)
            # Complete the dicts
            st_line_currency = st_line.currency_id or statement_currency
            st_line_currency_rate = st_line.currency_id and (
                st_line.amount_currency / st_line.amount) or False
            to_create = []
            for mv_line_dict in mv_line_dicts:
                if mv_line_dict.get('is_tax_line'):
                    continue
                mv_line_dict['bank_reconcile_id'] = bank_reconcile_id
                mv_line_dict['ref'] = move_name
                mv_line_dict['move_id'] = move_id
                mv_line_dict['period_id'] = st_line.statement_id.period_id.id
                mv_line_dict['journal_id'] = st_line.journal_id.id
                mv_line_dict['company_id'] = st_line.company_id.id
                mv_line_dict['statement_id'] = st_line.statement_id.id
                if mv_line_dict.get('counterpart_move_line_id'):
                    mv_line = aml_obj.browse(
                        cr,
                        uid,
                        mv_line_dict['counterpart_move_line_id'],
                        context=context)
                    mv_line_dict[
                        'partner_id'] = mv_line.partner_id.id or st_line.partner_id.id
                    mv_line_dict['account_id'] = mv_line.account_id.id
                if st_line_currency.id != company_currency.id:
                    ctx = context.copy()
                    ctx['date'] = st_line.date
                    mv_line_dict['amount_currency'] = mv_line_dict[
                        'debit'] - mv_line_dict['credit']
                    mv_line_dict['currency_id'] = st_line_currency.id
                    if st_line.currency_id and statement_currency.id == company_currency.id and st_line_currency_rate:
                        debit_at_current_rate = self.pool.get(
                            'res.currency').round(
                                cr, uid, company_currency,
                                mv_line_dict['debit'] / st_line_currency_rate)
                        credit_at_current_rate = self.pool.get(
                            'res.currency').round(
                                cr, uid, company_currency,
                                mv_line_dict['credit'] / st_line_currency_rate)
                    elif st_line.currency_id and st_line_currency_rate:
                        debit_at_current_rate = currency_obj.compute(
                            cr,
                            uid,
                            statement_currency.id,
                            company_currency.id,
                            mv_line_dict['debit'] / st_line_currency_rate,
                            context=ctx)
                        credit_at_current_rate = currency_obj.compute(
                            cr,
                            uid,
                            statement_currency.id,
                            company_currency.id,
                            mv_line_dict['credit'] / st_line_currency_rate,
                            context=ctx)
                    else:
                        debit_at_current_rate = currency_obj.compute(
                            cr,
                            uid,
                            st_line_currency.id,
                            company_currency.id,
                            mv_line_dict['debit'],
                            context=ctx)
                        credit_at_current_rate = currency_obj.compute(
                            cr,
                            uid,
                            st_line_currency.id,
                            company_currency.id,
                            mv_line_dict['credit'],
                            context=ctx)
                    if mv_line_dict.get('counterpart_move_line_id'):
                        # post an account line that use the same currency rate than the counterpart (to balance the account) and post the difference in another line
                        ctx['date'] = mv_line.date
                        if mv_line.currency_id.id == mv_line_dict['currency_id'] \
                                and float_is_zero(abs(mv_line.amount_currency) - abs(mv_line_dict['amount_currency']),
                                                  precision_rounding=mv_line.currency_id.rounding):
                            debit_at_old_rate = mv_line.credit
                            credit_at_old_rate = mv_line.debit
                        else:
                            debit_at_old_rate = currency_obj.compute(
                                cr,
                                uid,
                                st_line_currency.id,
                                company_currency.id,
                                mv_line_dict['debit'],
                                context=ctx)
                            credit_at_old_rate = currency_obj.compute(
                                cr,
                                uid,
                                st_line_currency.id,
                                company_currency.id,
                                mv_line_dict['credit'],
                                context=ctx)
                        mv_line_dict['credit'] = credit_at_old_rate
                        mv_line_dict['debit'] = debit_at_old_rate
                        if debit_at_old_rate - debit_at_current_rate:
                            currency_diff = debit_at_current_rate - debit_at_old_rate
                            to_create.append(
                                self.get_currency_rate_line(cr,
                                                            uid,
                                                            st_line,
                                                            -currency_diff,
                                                            move_id,
                                                            context=context))
                        if credit_at_old_rate - credit_at_current_rate:
                            currency_diff = credit_at_current_rate - credit_at_old_rate
                            to_create.append(
                                self.get_currency_rate_line(cr,
                                                            uid,
                                                            st_line,
                                                            currency_diff,
                                                            move_id,
                                                            context=context))
                        if mv_line.currency_id and mv_line_dict[
                                'currency_id'] == mv_line.currency_id.id:
                            amount_unreconciled = mv_line.amount_residual_currency
                        else:
                            amount_unreconciled = currency_obj.compute(
                                cr,
                                uid,
                                company_currency.id,
                                mv_line_dict['currency_id'],
                                mv_line.amount_residual,
                                context=ctx)
                        if float_is_zero(mv_line_dict['amount_currency'] +
                                         amount_unreconciled,
                                         precision_rounding=mv_line.
                                         currency_id.rounding):
                            amount = mv_line_dict['debit'] or mv_line_dict[
                                'credit']
                            sign = -1 if mv_line_dict['debit'] else 1
                            currency_rate_difference = sign * (
                                mv_line.amount_residual - amount)
                            if not company_currency.is_zero(
                                    currency_rate_difference):
                                exchange_lines = self._get_exchange_lines(
                                    cr,
                                    uid,
                                    st_line,
                                    mv_line,
                                    currency_rate_difference,
                                    mv_line_dict['currency_id'],
                                    move_id,
                                    context=context)
                                for exchange_line in exchange_lines:
                                    to_create.append(exchange_line)

                    else:
                        mv_line_dict['debit'] = debit_at_current_rate
                        mv_line_dict['credit'] = credit_at_current_rate
                elif statement_currency.id != company_currency.id:
                    # statement is in foreign currency but the transaction is in company currency
                    prorata_factor = (
                        mv_line_dict['debit'] -
                        mv_line_dict['credit']) / st_line.amount_currency
                    mv_line_dict[
                        'amount_currency'] = prorata_factor * st_line.amount
                to_create.append(mv_line_dict)
            # If the reconciliation is performed in another currency than the company currency, the amounts are converted to get the right debit/credit.
            # If there is more than 1 debit and 1 credit, this can induce a rounding error, which we put in the foreign exchane gain/loss account.
            if st_line_currency.id != company_currency.id:
                diff_amount = bank_st_move_vals['debit'] - bank_st_move_vals['credit'] \
                              + sum(aml['debit'] for aml in to_create) - sum(aml['credit'] for aml in to_create)
                if not company_currency.is_zero(diff_amount):
                    diff_aml = self.get_currency_rate_line(cr,
                                                           uid,
                                                           st_line,
                                                           diff_amount,
                                                           move_id,
                                                           context=context)
                    diff_aml['name'] = _(
                        'Rounding error from currency conversion')
                    to_create.append(diff_aml)
            # Create move lines
            move_line_pairs_to_reconcile = []
            for mv_line_dict in to_create:
                counterpart_move_line_id = None  # NB : this attribute is irrelevant for aml_obj.create() and needs to be removed from the dict
                if mv_line_dict.get('counterpart_move_line_id'):
                    counterpart_move_line_id = mv_line_dict[
                        'counterpart_move_line_id']
                    del mv_line_dict['counterpart_move_line_id']
                new_aml_id = aml_obj.create(cr,
                                            uid,
                                            mv_line_dict,
                                            context=context)
                if counterpart_move_line_id != None:
                    move_line_pairs_to_reconcile.append(
                        [new_aml_id, counterpart_move_line_id])
            # Reconcile
            #for pair in move_line_pairs_to_reconcile:
            #    aml_obj.reconcile_partial(cr, uid, pair, context=context)
            # Mark the statement line as reconciled
            self.write(cr,
                       uid,
                       id, {'journal_entry_id': move_id},
                       context=context)
Exemple #32
0
    def process_sheet(self, cr, uid, ids, context=None):
        move_pool = self.pool.get('account.move')
        hr_payslip_line_pool = self.pool['hr.payslip.line']
        precision = self.pool.get('decimal.precision').precision_get(
            cr, uid, 'Payroll')

        for slip in self.browse(cr, uid, ids, context=context):
            line_ids = []
            debit_sum = 0.0
            credit_sum = 0.0
            date = slip.date or slip.date_to

            partner_eps_id = slip.employee_id.eps_id.id
            partner_fp_id = slip.employee_id.fp_id.id
            partner_fc_id = slip.employee_id.fc_id.id

            default_partner_id = slip.employee_id.address_home_id.id

            name = _('Payslip of %s') % (slip.employee_id.name)
            move = {
                'narration': name,
                'ref': slip.number,
                'journal_id': slip.journal_id.id,
                'date': date,
            }
            for line in slip.details_by_salary_rule_category:
                amt = slip.credit_note and -line.total or line.total
                if float_is_zero(amt, precision_digits=precision):
                    continue

                partner_id = line.salary_rule_id.register_id.partner_id and line.salary_rule_id.register_id.partner_id.id or default_partner_id

                debit_account_id = line.salary_rule_id.account_debit.id
                credit_account_id = line.salary_rule_id.account_credit.id

                if line.salary_rule_id.origin_partner == 'employee':
                    partner_id = default_partner_id
                elif line.salary_rule_id.origin_partner == 'eps':
                    partner_id = partner_eps_id
                elif line.salary_rule_id.origin_partner == 'fp':
                    partner_id = partner_fp_id
                elif line.salary_rule_id.origin_partner == 'fc':
                    partner_id = partner_fc_id
                elif line.salary_rule_id.origin_partner == 'rule':
                    partner_id = line.salary_rule_id.partner_id.id
                else:
                    partner_id = default_partner_id

                if debit_account_id:
                    debit_line = (
                        0,
                        0,
                        {
                            'name':
                            line.name,
                            # 'partner_id': hr_payslip_line_pool._get_partner_id(cr, uid, line, credit_account=False, context=context),
                            'partner_id':
                            partner_id,
                            'account_id':
                            debit_account_id,
                            'journal_id':
                            slip.journal_id.id,
                            'date':
                            date,
                            'debit':
                            amt > 0.0 and amt or 0.0,
                            'credit':
                            amt < 0.0 and -amt or 0.0,
                            'analytic_account_id':
                            line.salary_rule_id.analytic_account_id
                            and line.salary_rule_id.analytic_account_id.id
                            or False,
                            'tax_line_id':
                            line.salary_rule_id.account_tax_id
                            and line.salary_rule_id.account_tax_id.id or False,
                        })
                    line_ids.append(debit_line)
                    debit_sum += debit_line[2]['debit'] - debit_line[2][
                        'credit']

                if credit_account_id:
                    credit_line = (
                        0,
                        0,
                        {
                            'name':
                            line.name,
                            # 'partner_id': hr_payslip_line_pool._get_partner_id(cr, uid, line, credit_account=True, context=context),
                            'partner_id':
                            partner_id,
                            'account_id':
                            credit_account_id,
                            'journal_id':
                            slip.journal_id.id,
                            'date':
                            date,
                            'debit':
                            amt < 0.0 and -amt or 0.0,
                            'credit':
                            amt > 0.0 and amt or 0.0,
                            'analytic_account_id':
                            line.salary_rule_id.analytic_account_id
                            and line.salary_rule_id.analytic_account_id.id
                            or False,
                            'tax_line_id':
                            line.salary_rule_id.account_tax_id
                            and line.salary_rule_id.account_tax_id.id or False,
                        })
                    line_ids.append(credit_line)
                    credit_sum += credit_line[2]['credit'] - credit_line[2][
                        'debit']

            if float_compare(credit_sum, debit_sum,
                             precision_digits=precision) == -1:
                acc_id = slip.journal_id.default_credit_account_id.id
                if not acc_id:
                    raise UserError(
                        _('The Expense Journal "%s" has not properly configured the Credit Account!'
                          ) % (slip.journal_id.name))
                adjust_credit = (0, 0, {
                    'name': _('Adjustment Entry'),
                    'partner_id': False,
                    'account_id': acc_id,
                    'journal_id': slip.journal_id.id,
                    'date': date,
                    'debit': 0.0,
                    'credit': debit_sum - credit_sum,
                })
                line_ids.append(adjust_credit)

            elif float_compare(debit_sum,
                               credit_sum,
                               precision_digits=precision) == -1:
                acc_id = slip.journal_id.default_debit_account_id.id
                if not acc_id:
                    raise UserError(
                        _('The Expense Journal "%s" has not properly configured the Debit Account!'
                          ) % (slip.journal_id.name))
                adjust_debit = (0, 0, {
                    'name': _('Adjustment Entry'),
                    'partner_id': False,
                    'account_id': acc_id,
                    'journal_id': slip.journal_id.id,
                    'date': date,
                    'debit': credit_sum - debit_sum,
                    'credit': 0.0,
                })
                line_ids.append(adjust_debit)

            move.update({'line_ids': line_ids})
            move_id = move_pool.create(cr, uid, move, context=context)
            self.write(cr,
                       uid, [slip.id], {
                           'move_id': move_id,
                           'date': date,
                           'state': 'done',
                           'paid': True
                       },
                       context=context)
            move_pool.post(cr, uid, [move_id], context=context)
        return True
Exemple #33
0
    def _process_order(self, cr, uid, order, context=None):
        order_id = self.create(
            cr, uid, self._order_fields(cr, uid, order, context=context),
            context)

        for payments in order['statement_ids']:
            if not order.get('sale_mode') and order.get(
                    'parent_return_order', ''):
                payments[2]['amount'] = payments[2]['amount'] or 0.0
            self.add_payment(cr,
                             uid,
                             order_id,
                             self._payment_fields(cr,
                                                  uid,
                                                  payments[2],
                                                  context=context),
                             context=context)

        session = self.pool.get('pos.session').browse(cr,
                                                      uid,
                                                      order['pos_session_id'],
                                                      context=context)
        if session.sequence_number <= order['sequence_number']:
            session.write({'sequence_number': order['sequence_number'] + 1})
            session.refresh()

        if not order.get('parent_return_order', '') and not float_is_zero(
                order['amount_return'],
                self.pool.get('decimal.precision').precision_get(
                    cr, uid, 'Account')):
            cash_journal = session.cash_journal_id
            if not cash_journal:
                cash_journal_ids = filter(
                    lambda st: st.journal_id.type == 'cash',
                    session.statement_ids)
                if not len(cash_journal_ids):
                    raise osv.except_osv(
                        _('error!'),
                        _("No cash statement found for this session. Unable to record returned cash."
                          ))
                cash_journal = cash_journal_ids[0].journal_id
            self.add_payment(
                cr,
                uid,
                order_id, {
                    'amount': -order['amount_return'],
                    'payment_date': time.strftime('%Y-%m-%d %H:%M:%S'),
                    'payment_name': _('return'),
                    'journal': cash_journal.id,
                },
                context=context)

        if order.get('parent_return_order', '') and not float_is_zero(
                order['amount_return'],
                self.pool.get('decimal.precision').precision_get(
                    cr, uid, 'Account')):
            cash_journal = session.cash_journal_id
            if not cash_journal:
                cash_journal_ids = filter(
                    lambda st: st.journal_id.type == 'cash',
                    session.statement_ids)
                if not len(cash_journal_ids):
                    raise osv.except_osv(
                        _('error!'),
                        _("No cash statement found for this session. Unable to record returned cash."
                          ))
                cash_journal = cash_journal_ids[0].journal_id
            self.add_payment(
                cr,
                uid,
                order_id, {
                    'amount': -order['amount_return'],
                    'payment_date': time.strftime('%Y-%m-%d %H:%M:%S'),
                    'payment_name': _('return'),
                    'journal': cash_journal.id,
                },
                context=context)

        return order_id
    def process_sheet(self):
        move_pool = self.env['account.move']
        precision = self.env['decimal.precision'].precision_get('Payroll')
        timenow = time.strftime('%Y-%m-%d')

        for slip in self:
            line_ids = []
            debit_sum = 0.0
            credit_sum = 0.0

            employee_partner = slip.employee_id.address_home_id
            name = _('Payslip of %s') % (slip.employee_id.name)
            move_vals = {
                'narration': name,
                'date': timenow,
                'ref': slip.number,
                'journal_id': slip.journal_id.id,
            }
            for line in slip.details_by_salary_rule_category:
                amt = -line.amount if slip.credit_note else line.amount

                if float_is_zero(amt, precision_digits=precision):
                    continue

                rule = line.salary_rule_id
                register_partner = rule.register_id.partner_id

                debit_account_id = line.salary_rule_id.account_debit.id
                credit_account_id = line.salary_rule_id.account_credit.id
                analytic_account = rule.analytic_account_id

                if debit_account_id:

                    if (rule.account_debit.internal_type
                            not in ['receivable', 'payable']):
                        partner_debit = self.env['res.partner']

                    elif register_partner:
                        partner_debit = register_partner

                    else:
                        partner_debit = employee_partner

                    debit_line = (0, 0, {
                        'name': line.name,
                        'date': timenow,
                        'partner_id': partner_debit.id,
                        'account_id': debit_account_id,
                        'journal_id': slip.journal_id.id,
                        'debit': amt > 0.0 and amt or 0.0,
                        'credit': amt < 0.0 and -amt or 0.0,
                        'analytic_account_id': analytic_account.id,
                    })
                    line_ids.append(debit_line)
                    debit_sum += (debit_line[2]['debit'] -
                                  debit_line[2]['credit'])

                if credit_account_id:

                    if (rule.account_credit.internal_type
                            not in ['receivable', 'payable']):
                        partner_credit = self.env['res.partner']

                    elif register_partner:
                        partner_credit = register_partner

                    else:
                        partner_credit = employee_partner

                    credit_line = (0, 0, {
                        'name': line.name,
                        'date': timenow,
                        'partner_id': partner_credit.id,
                        'account_id': credit_account_id,
                        'journal_id': slip.journal_id.id,
                        'debit': amt < 0.0 and -amt or 0.0,
                        'credit': amt > 0.0 and amt or 0.0,
                        'analytic_account_id': analytic_account.id,
                    })
                    line_ids.append(credit_line)
                    credit_sum += (credit_line[2]['credit'] -
                                   credit_line[2]['debit'])

            if (float_compare(credit_sum,
                              debit_sum,
                              precision_digits=precision) == -1):
                acc_id = slip.journal_id.default_credit_account_id.id
                if not acc_id:
                    raise ValidationError(
                        _('The Expense Journal "%s" has not properly configured '
                          'the Credit Account!') % slip.journal_id.name)
                adjust_credit = (0, 0, {
                    'name': _('Adjustment Entry'),
                    'date': timenow,
                    'partner_id': False,
                    'account_id': acc_id,
                    'journal_id': slip.journal_id.id,
                    'debit': 0.0,
                    'credit': debit_sum - credit_sum,
                })
                line_ids.append(adjust_credit)

            elif (float_compare(debit_sum,
                                credit_sum,
                                precision_digits=precision) == -1):
                acc_id = slip.journal_id.default_debit_account_id.id
                if not acc_id:
                    raise ValidationError(
                        _('The Expense Journal "%s" has not properly configured '
                          'the Debit Account!') % slip.journal_id.name)
                adjust_debit = (0, 0, {
                    'name': _('Adjustment Entry'),
                    'date': timenow,
                    'partner_id': False,
                    'account_id': acc_id,
                    'journal_id': slip.journal_id.id,
                    'debit': credit_sum - debit_sum,
                    'credit': 0.0,
                })
                line_ids.append(adjust_debit)

            move_vals.update({'line_ids': line_ids})
            move = move_pool.create(move_vals)
            slip.write({'move_id': move.id})

        return super(HrPayslip, self).process_sheet()
Exemple #35
0
    def process_sheet(self, cr, uid, ids, context=None):
        move_pool = self.pool.get('account.move')
        period_pool = self.pool.get('account.period')
        precision = self.pool.get('decimal.precision').precision_get(
            cr, uid, 'Payroll')
        timenow = time.strftime('%Y-%m-%d')

        for slip in self.browse(cr, uid, ids, context=context):
            line_ids = []
            debit_sum = 0.0
            credit_sum = 0.0
            if not slip.period_id:
                search_periods = period_pool.find(cr,
                                                  uid,
                                                  slip.date_to,
                                                  context=context)
                period_id = search_periods[0]
            else:
                period_id = slip.period_id.id

            default_partner_id = slip.employee_id.address_home_id.id
            name = _('Payslip of %s') % (slip.employee_id.name)
            move = {
                'narration': name,
                'date': timenow,
                'ref': slip.number,
                'journal_id': slip.journal_id.id,
                'period_id': period_id,
            }
            for line in slip.details_by_salary_rule_category:
                amt = slip.credit_note and -line.total or line.total
                if float_is_zero(amt, precision_digits=precision):
                    continue
                partner_id = line.salary_rule_id.register_id.partner_id and line.salary_rule_id.register_id.partner_id.id or default_partner_id
                debit_account_id = line.salary_rule_id.account_debit.id
                credit_account_id = line.salary_rule_id.account_credit.id

                if debit_account_id:

                    debit_line = (0, 0, {
                        'name':
                        line.name,
                        'date':
                        timenow,
                        'partner_id':
                        (line.salary_rule_id.register_id.partner_id
                         or line.salary_rule_id.account_debit.type in
                         ('receivable', 'payable')) and partner_id or False,
                        'account_id':
                        debit_account_id,
                        'journal_id':
                        slip.journal_id.id,
                        'period_id':
                        period_id,
                        'debit':
                        amt > 0.0 and amt or 0.0,
                        'credit':
                        amt < 0.0 and -amt or 0.0,
                        'analytic_account_id':
                        line.salary_rule_id.analytic_account_id
                        and line.salary_rule_id.analytic_account_id.id
                        or False,
                        'tax_code_id':
                        line.salary_rule_id.account_tax_id
                        and line.salary_rule_id.account_tax_id.id or False,
                        'tax_amount':
                        line.salary_rule_id.account_tax_id and amt or 0.0,
                    })
                    line_ids.append(debit_line)
                    debit_sum += debit_line[2]['debit'] - debit_line[2][
                        'credit']

                if credit_account_id:

                    credit_line = (0, 0, {
                        'name':
                        line.name,
                        'date':
                        timenow,
                        'partner_id':
                        (line.salary_rule_id.register_id.partner_id
                         or line.salary_rule_id.account_credit.type in
                         ('receivable', 'payable')) and partner_id or False,
                        'account_id':
                        credit_account_id,
                        'journal_id':
                        slip.journal_id.id,
                        'period_id':
                        period_id,
                        'debit':
                        amt < 0.0 and -amt or 0.0,
                        'credit':
                        amt > 0.0 and amt or 0.0,
                        'analytic_account_id':
                        line.salary_rule_id.analytic_account_id
                        and line.salary_rule_id.analytic_account_id.id
                        or False,
                        'tax_code_id':
                        line.salary_rule_id.account_tax_id
                        and line.salary_rule_id.account_tax_id.id or False,
                        'tax_amount':
                        line.salary_rule_id.account_tax_id and amt or 0.0,
                    })
                    line_ids.append(credit_line)
                    credit_sum += credit_line[2]['credit'] - credit_line[2][
                        'debit']

            if float_compare(credit_sum, debit_sum,
                             precision_digits=precision) == -1:
                acc_id = slip.journal_id.default_credit_account_id.id
                if not acc_id:
                    raise UserError(
                        _('The Expense Journal "%s" has not properly configured the Credit Account!'
                          ) % (slip.journal_id.name))
                adjust_credit = (0, 0, {
                    'name': _('Adjustment Entry'),
                    'date': timenow,
                    'partner_id': False,
                    'account_id': acc_id,
                    'journal_id': slip.journal_id.id,
                    'period_id': period_id,
                    'debit': 0.0,
                    'credit': debit_sum - credit_sum,
                })
                line_ids.append(adjust_credit)

            elif float_compare(debit_sum,
                               credit_sum,
                               precision_digits=precision) == -1:
                acc_id = slip.journal_id.default_debit_account_id.id
                if not acc_id:
                    raise UserError(
                        _('The Expense Journal "%s" has not properly configured the Debit Account!'
                          ) % (slip.journal_id.name))
                adjust_debit = (0, 0, {
                    'name': _('Adjustment Entry'),
                    'date': timenow,
                    'partner_id': False,
                    'account_id': acc_id,
                    'journal_id': slip.journal_id.id,
                    'period_id': period_id,
                    'debit': credit_sum - debit_sum,
                    'credit': 0.0,
                })
                line_ids.append(adjust_debit)

            move.update({'line_id': line_ids})
            move_id = move_pool.create(cr, uid, move, context=context)
            self.write(cr,
                       uid, [slip.id], {
                           'move_id': move_id,
                           'period_id': period_id
                       },
                       context=context)
            if slip.journal_id.entry_posted:
                move_pool.post(cr, uid, [move_id], context=context)
        return super(hr_payslip, self).process_sheet(cr,
                                                     uid, [slip.id],
                                                     context=context)
Exemple #36
0
    def _add_trade_settlement_block(self, trade_transaction, sign, ns):
        self.ensure_one()
        prec = self.env['decimal.precision'].precision_get('Account')
        inv_currency_name = self.currency_id.name
        trade_settlement = etree.SubElement(
            trade_transaction,
            ns['ram'] + 'ApplicableSupplyChainTradeSettlement')
        payment_ref = etree.SubElement(trade_settlement,
                                       ns['ram'] + 'PaymentReference')
        payment_ref.text = self.number or self.state
        invoice_currency = etree.SubElement(trade_settlement,
                                            ns['ram'] + 'InvoiceCurrencyCode')
        invoice_currency.text = inv_currency_name
        if (self.payment_mode_id and not self.payment_mode_id.type.unece_code):
            raise UserError(
                _("Missing UNECE code on payment export type '%s'") %
                self.payment_mode_id.type.name)
        if (self.type == 'out_invoice'
                or (self.payment_mode_id
                    and self.payment_mode_id.type.unece_code not in [31, 42])):
            self._add_trade_settlement_payment_means_block(
                trade_settlement, sign, ns)
        tax_basis_total = 0.0
        if self.tax_line:
            for tline in self.tax_line:
                if not tline.base_code_id:
                    raise UserError(
                        _("Missing base code on tax line '%s'.") % tline.name)
                taxes = self.env['account.tax'].search([
                    ('base_code_id', '=', tline.base_code_id.id)
                ])
                if not taxes:
                    raise UserError(
                        _("The tax code '%s' is not linked to a tax.") %
                        tline.base_code_id.name)
                tax = taxes[0]
                if not tax.unece_type_code:
                    raise UserError(
                        _("Missing UNECE Tax Type on tax '%s'") % tax.name)
                if not tax.unece_categ_code:
                    raise UserError(
                        _("Missing UNECE Tax Category on tax '%s'") % tax.name)
                trade_tax = etree.SubElement(trade_settlement,
                                             ns['ram'] + 'ApplicableTradeTax')
                amount = etree.SubElement(trade_tax,
                                          ns['ram'] + 'CalculatedAmount',
                                          currencyID=inv_currency_name)
                amount.text = unicode(tline.amount * sign)
                tax_type = etree.SubElement(trade_tax, ns['ram'] + 'TypeCode')
                tax_type.text = tax.unece_type_code

                if (tax.unece_categ_code != 'S'
                        and float_is_zero(tax.amount, precision_digits=prec)
                        and self.fiscal_position
                        and self.fiscal_position.note):
                    exemption_reason = etree.SubElement(
                        trade_tax, ns['ram'] + 'ExemptionReason')
                    exemption_reason.text = self.with_context(
                        lang=self.partner_id.lang or 'en_US').\
                        fiscal_position.note

                base = etree.SubElement(trade_tax,
                                        ns['ram'] + 'BasisAmount',
                                        currencyID=inv_currency_name)
                base.text = unicode(tline.base * sign)
                tax_basis_total += tline.base
                tax_categ_code = etree.SubElement(trade_tax,
                                                  ns['ram'] + 'CategoryCode')
                tax_categ_code.text = tax.unece_categ_code
                if tax.type == 'percent':
                    percent = etree.SubElement(trade_tax,
                                               ns['ram'] + 'ApplicablePercent')
                    percent.text = unicode(tax.amount * 100)
        trade_payment_term = etree.SubElement(
            trade_settlement, ns['ram'] + 'SpecifiedTradePaymentTerms')
        trade_payment_term_desc = etree.SubElement(trade_payment_term,
                                                   ns['ram'] + 'Description')
        # The 'Description' field of SpecifiedTradePaymentTerms
        # is a required field, so we must always give a value
        if self.payment_term:
            trade_payment_term_desc.text = self.payment_term.name
        else:
            trade_payment_term_desc.text =\
                _('No specific payment term selected')

        if self.date_due:
            date_due_dt = fields.Date.from_string(self.date_due)
            self._add_date('DueDateDateTime', date_due_dt, trade_payment_term,
                           ns)

        sums = etree.SubElement(
            trade_settlement,
            ns['ram'] + 'SpecifiedTradeSettlementMonetarySummation')
        line_total = etree.SubElement(sums,
                                      ns['ram'] + 'LineTotalAmount',
                                      currencyID=inv_currency_name)
        line_total.text = unicode(self.amount_untaxed * sign)
        charge_total = etree.SubElement(sums,
                                        ns['ram'] + 'ChargeTotalAmount',
                                        currencyID=inv_currency_name)
        charge_total.text = '0.00'
        allowance_total = etree.SubElement(sums,
                                           ns['ram'] + 'AllowanceTotalAmount',
                                           currencyID=inv_currency_name)
        allowance_total.text = '0.00'
        tax_basis_total_amt = etree.SubElement(sums,
                                               ns['ram'] +
                                               'TaxBasisTotalAmount',
                                               currencyID=inv_currency_name)
        tax_basis_total_amt.text = unicode(tax_basis_total * sign)
        tax_total = etree.SubElement(sums,
                                     ns['ram'] + 'TaxTotalAmount',
                                     currencyID=inv_currency_name)
        tax_total.text = unicode(self.amount_tax * sign)
        total = etree.SubElement(sums,
                                 ns['ram'] + 'GrandTotalAmount',
                                 currencyID=inv_currency_name)
        total.text = unicode(self.amount_total * sign)
        prepaid = etree.SubElement(sums,
                                   ns['ram'] + 'TotalPrepaidAmount',
                                   currencyID=inv_currency_name)
        residual = etree.SubElement(sums,
                                    ns['ram'] + 'DuePayableAmount',
                                    currencyID=inv_currency_name)
        prepaid.text = unicode((self.amount_total - self.residual) * sign)
        residual.text = unicode(self.residual * sign)
Exemple #37
0
    def _get_billwise_move_lines(self, account_type, date_from, target_move,
                                 period_length):
        periods = {}
        start = datetime.strptime(date_from, "%Y-%m-%d")
        for i in range(5)[::-1]:
            stop = start - relativedelta(days=period_length)
            periods[str(i)] = {
                'name': (i != 0 and (str(
                    (5 - (i + 1)) * period_length) + '-' + str(
                        (5 - i) * period_length))
                         or ('+' + str(4 * period_length))),
                'stop':
                start.strftime('%Y-%m-%d'),
                'start': (i != 0 and stop.strftime('%Y-%m-%d') or False),
            }
            start = stop - relativedelta(days=1)
        res = []
        total = []
        cr = self.env.cr
        user_company = self.env.user.company_id.id
        move_state = ['draft', 'posted']
        if target_move == 'posted':
            move_state = ['posted']
        arg_list = (tuple(move_state), tuple(account_type))
        #build the reconciliation clause to see what partner needs to be printed
        reconciliation_clause = '(l.reconciled IS FALSE)'
        cr.execute(
            'SELECT debit_move_id, credit_move_id FROM account_partial_reconcile where create_date > %s',
            (date_from, ))
        reconciled_after_date = []
        for row in cr.fetchall():
            reconciled_after_date += [row[0], row[1]]
        if reconciled_after_date:
            reconciliation_clause = '(l.reconciled IS FALSE OR l.id IN %s)'
            arg_list += (tuple(reconciled_after_date), )
        arg_list += (date_from, user_company)
        query = '''
            SELECT DISTINCT l.partner_id, UPPER(res_partner.name)
            FROM account_move_line AS l left join res_partner on l.partner_id = res_partner.id, account_account, account_move am
            WHERE (l.account_id = account_account.id)
                AND (l.move_id = am.id)
                AND (am.state IN %s)
                AND (account_account.internal_type IN %s)
                AND ''' + reconciliation_clause + '''
                AND (l.date <= %s)
                AND l.company_id = %s
            ORDER BY UPPER(res_partner.name)'''
        cr.execute(query, arg_list)

        partners = cr.dictfetchall()
        # put a total of 0
        for i in range(7):
            total.append(0)

        # Build a string like (1,2,3) for easy use in SQL query
        partner_ids = [
            partner['partner_id'] for partner in partners
            if partner['partner_id']
        ]
        lines = dict(
            (partner['partner_id'] or False, []) for partner in partners)
        if not partner_ids:
            return [], [], []

        # This dictionary will store the not due amount of all partners
        undue_amounts = {}
        query = '''SELECT l.id
                FROM account_move_line AS l, account_account, account_move am
                WHERE (l.account_id = account_account.id) AND (l.move_id = am.id)
                    AND (am.state IN %s)
                    AND (account_account.internal_type IN %s)
                    AND (COALESCE(l.date_maturity,l.date) > %s)\
                    AND ((l.partner_id IN %s) OR (l.partner_id IS NULL))
                AND (l.date <= %s)
                AND l.company_id = %s'''
        cr.execute(query, (tuple(move_state), tuple(account_type), date_from,
                           tuple(partner_ids), date_from, user_company))
        aml_ids = cr.fetchall()
        aml_ids = aml_ids and [x[0] for x in aml_ids] or []
        for line in self.env['account.move.line'].browse(aml_ids):
            partner_id = line.partner_id.id or False
            if partner_id not in undue_amounts:
                undue_amounts[partner_id] = 0.0
            line_amount = line.balance
            if line.balance == 0:
                continue
            for partial_line in line.matched_debit_ids:
                if partial_line.create_date[:10] <= date_from:
                    line_amount += partial_line.amount
            for partial_line in line.matched_credit_ids:
                if partial_line.create_date[:10] <= date_from:
                    line_amount -= partial_line.amount
            undue_amounts[partner_id] += line_amount
            lines[partner_id].append({
                'line': line,
                'amount': line_amount,
                'period': 6,
            })
        # Use one query per period and store results in history (a list variable)
        # Each history will contain: history[1] = {'<partner_id>': <partner_debit-credit>}
        history = []
        for i in range(5):
            args_list = (
                tuple(move_state),
                tuple(account_type),
                tuple(partner_ids),
            )
            dates_query = '(COALESCE(l.date_maturity,l.date)'

            if periods[str(i)]['start'] and periods[str(i)]['stop']:
                dates_query += ' BETWEEN %s AND %s)'
                args_list += (periods[str(i)]['start'],
                              periods[str(i)]['stop'])
            elif periods[str(i)]['start']:
                dates_query += ' >= %s)'
                args_list += (periods[str(i)]['start'], )
            else:
                dates_query += ' <= %s)'
                args_list += (periods[str(i)]['stop'], )
            args_list += (date_from, user_company)

            query = '''SELECT l.id
                    FROM account_move_line AS l, account_account, account_move am
                    WHERE (l.account_id = account_account.id) AND (l.move_id = am.id)
                        AND (am.state IN %s)
                        AND (account_account.internal_type IN %s)
                        AND ((l.partner_id IN %s) OR (l.partner_id IS NULL))
                        AND ''' + dates_query + '''
                    AND (l.date <= %s)
                    AND l.company_id = %s'''
            cr.execute(query, args_list)
            partners_amount = {}
            aml_ids = cr.fetchall()
            aml_ids = aml_ids and [x[0] for x in aml_ids] or []
            for line in self.env['account.move.line'].browse(aml_ids):
                partner_id = line.partner_id.id or False
                if partner_id not in partners_amount:
                    partners_amount[partner_id] = 0.0
                line_amount = line.balance
                if line.balance == 0:
                    continue
                for partial_line in line.matched_debit_ids:
                    if partial_line.create_date[:10] <= date_from:
                        line_amount += partial_line.amount
                for partial_line in line.matched_credit_ids:
                    if partial_line.create_date[:10] <= date_from:
                        line_amount -= partial_line.amount

                partners_amount[partner_id] += line_amount
                lines[partner_id].append({
                    'line': line,
                    'amount': line_amount,
                    'period': i + 1,
                })
            history.append(partners_amount)
        for partner in partners:
            at_least_one_amount = False
            values = {}
            undue_amt = 0.0
            if partner[
                    'partner_id'] in undue_amounts:  # Making sure this partner actually was found by the query
                undue_amt = undue_amounts[partner['partner_id']]

            total[6] = total[6] + undue_amt
            values['direction'] = undue_amt
            if not float_is_zero(values['direction'],
                                 precision_rounding=self.env.user.company_id.
                                 currency_id.rounding):
                at_least_one_amount = True

            for i in range(5):
                during = False
                if partner['partner_id'] in history[i]:
                    during = [history[i][partner['partner_id']]]
                # Adding counter
                total[(i)] = total[(i)] + (during and during[0] or 0)
                values[str(i)] = during and during[0] or 0.0
                if not float_is_zero(values[str(i)],
                                     precision_rounding=self.env.user.
                                     company_id.currency_id.rounding):
                    at_least_one_amount = True
            values['total'] = sum([values['direction']] +
                                  [values[str(i)] for i in range(5)])
            ## Add for total
            total[(i + 1)] += values['total']
            values['partner_id'] = partner['partner_id']
            if partner['partner_id']:
                browsed_partner = self.env['res.partner'].browse(
                    partner['partner_id'])
                values['name'] = browsed_partner.name and len(
                    browsed_partner.name) >= 45 and browsed_partner.name[
                        0:40] + '...' or browsed_partner.name
                values['trust'] = False
            else:
                values['name'] = _('Unknown Partner')
                values['trust'] = False
            if at_least_one_amount:
                res.append(values)

        return res, total, lines
    def button_validate(self):
        self.ensure_one()
        precision_obj = self.pool.get('decimal.precision').precision_get(
            self._cr, self._uid, 'Account')
        quant_obj = self.env['stock.quant']
        template_obj = self.pool.get('product.template')
        scp_obj = self.env['stock.card.product']
        get_average = scp_obj.get_average
        stock_card_move_get = scp_obj._stock_card_move_get
        ctx = dict(self._context)

        for cost in self:
            if cost.state != 'draft':
                raise UserError(_('Only draft landed costs can be validated'))
            if not cost.valuation_adjustment_lines or \
                    not self._check_sum(cost):
                raise UserError(
                    _('You cannot validate a landed cost which has no valid '
                      'valuation adjustments lines. Did you click on '
                      'Compute?'))

            move_id = self._model._create_account_move(self._cr,
                                                       self._uid,
                                                       cost,
                                                       context=ctx)
            prod_dict = {}
            init_avg = {}
            first_lines = {}
            first_card = {}
            last_lines = {}
            prod_qty = {}
            acc_prod = {}
            quant_dict = {}
            for line in cost.valuation_adjustment_lines:
                if not line.move_id:
                    continue
                product_id = line.product_id

                if product_id.id not in acc_prod:
                    acc_prod[product_id.id] = \
                        template_obj.get_product_accounts(
                        self._cr, self._uid, product_id.product_tmpl_id.id,
                        context=ctx)

                if product_id.cost_method == 'standard':
                    self._create_standard_deviation_entries(
                        line, move_id, acc_prod)
                    continue

                if product_id.cost_method == 'average':
                    if product_id.id not in prod_dict:
                        first_card = stock_card_move_get(product_id.id)
                        prod_dict[product_id.id] = get_average(first_card)
                        first_lines[product_id.id] = first_card['res']
                        init_avg[product_id.id] = product_id.standard_price
                        prod_qty[product_id.id] = first_card['product_qty']

                per_unit = line.final_cost / line.quantity
                diff = per_unit - line.former_cost_per_unit
                quants = [quant for quant in line.move_id.quant_ids]
                for quant in quants:
                    if quant.id not in quant_dict:
                        quant_dict[quant.id] = quant.cost + diff
                    else:
                        quant_dict[quant.id] += diff

                qty_out = 0
                for quant in line.move_id.quant_ids:
                    if quant.location_id.usage != 'internal':
                        qty_out += quant.qty

                if product_id.cost_method == 'average':
                    # /!\ NOTE: Inventory valuation
                    self._create_landed_accounting_entries(
                        line, move_id, 0.0, acc_prod)

                if product_id.cost_method == 'real':
                    self._create_landed_accounting_entries(
                        line, move_id, qty_out, acc_prod)

            for key, value in quant_dict.items():
                quant_obj.sudo().browse(key).write({'cost': value})

            # /!\ NOTE: This new update is taken out of for loop to improve
            # performance
            for prod_id in prod_dict:
                last_card = stock_card_move_get(prod_id)
                prod_dict[prod_id] = get_average(last_card)
                last_lines[prod_id] = last_card['res']

            # /!\ NOTE: COGS computation
            # NOTE: After adding value to product with landing cost products
            # with costing method `average` need to be check in order to
            # find out the change in COGS in case of sales were performed prior
            # to landing costs
            to_cogs = {}
            for prod_id in prod_dict:
                to_cogs[prod_id] = zip(first_lines[prod_id],
                                       last_lines[prod_id])
            for prod_id in to_cogs:
                fst_avg = 0.0
                lst_avg = 0.0
                ini_avg = init_avg[prod_id]
                diff = 0.0
                for tpl in to_cogs[prod_id]:
                    first_line = tpl[0]
                    last_line = tpl[1]
                    fst_avg = first_line['average']
                    lst_avg = last_line['average']
                    if first_line['qty'] >= 0:
                        # /!\ TODO: This is not true for devolutions
                        continue

                    # NOTE: Rounding problems could arise here, this needs to
                    # be checked
                    diff += (lst_avg - fst_avg) * abs(first_line['qty'])
                if not float_is_zero(diff, precision_obj):
                    self._create_cogs_accounting_entries(
                        prod_id, move_id, diff, acc_prod)

                # TODO: Compute deviation
                diff = 0.0
                if prod_qty[prod_id] and fst_avg != ini_avg and \
                        lst_avg != ini_avg:
                    diff = (fst_avg - ini_avg) * prod_qty[prod_id]
                    if not float_is_zero(diff, precision_obj):
                        self._create_deviation_accounting_entries(
                            move_id, prod_id, diff, acc_prod)

            # TODO: Write latest value for average
            cost.compute_average_cost(prod_dict)

            cost.write({'state': 'done', 'account_move_id': move_id})

            # Post the account move if the journal's auto post true
            move_obj = self.env['account.move'].browse(move_id)
            if move_obj.journal_id.entry_posted:
                move_obj.post()
                move_obj.validate()

        return True
Exemple #39
0
 def _evaluate_threshold(self, bottom_th, computed_th, diff):
     """ Checks if bottom threshold is reached by computed threshold """
     precision_id = self.env['decimal.precision'].precision_get('Account')
     return float_is_zero(diff, precision_id) or\
         (self.standard_price and diff < 0 and
          computed_th > bottom_th)
    def __execute_cron(self, cr, uid, ids=None, context=None):  # noqa
        """This method is incorrectly designed due to the write on the product as
         obsolete should be a core feature not a cron feature.

         I do not delete it because I need review afterwards such feature.

         Dear Future me I am really sorry
        """
        ids = ids or []
        context = context or {}
        product_obj = self.pool.get('product.product')
        precision_obj = self.pool.get('decimal.precision').precision_get(
            cr, uid, 'Account')
        user = self.pool.get('res.users').browse(cr, uid, uid, context)
        std_bottom_threshold = user.company_id.std_price_neg_threshold
        product_ids = self._get_products(cr, uid, ids, context=context)
        message = 'Old price %(old)s, New price %(new)s'
        context['message'] = ''
        count = 0
        total = len(product_ids)
        _logger.info('Cron Job will compute %(length)s products',
                     dict(length=total))
        msglog = 'Computing cost for product: [{prod_id}]. {count}/{total}'
        for product in product_ids:
            prod_brw = product_obj.browse(cr, uid, product)
            count += 1
            _logger.info(msglog, dict(prod_id=product,
                                      total=total,
                                      count=count))

            if product_obj.fetch_product_bom_states(cr,
                                                    uid,
                                                    product,
                                                    state='obsolete',
                                                    context=context):
                _logger.warning('product [%s] has obsolete children', product)
                continue

            # /!\ NOTE: Is it enough to call the qty like that?
            if prod_brw.qty_available == 0:
                prod_brw.write({'state': 'obsolete'})
                continue
            context.update({
                'active_model': 'product.product',
                'active_id': product
            })
            std_preview = self._onchange_recursive(cr,
                                                   uid,
                                                   ids,
                                                   recursive=True,
                                                   context=context).get(
                                                       product, 0.0)
            old = prod_brw.standard_price
            diff = std_preview - old

            # /!\ NOTE: Is it the right precision
            if float_is_zero(diff, precision_obj):
                # Do not update it is worthless
                continue

            if old and diff / old < std_bottom_threshold and \
                    prod_brw.qty_available > 0 and \
                    prod_brw.state != 'end':
                # Write product as obsolete
                # /!\ NOTE: Will not this cause more concurrence
                prod_brw.write({'state': 'end'})

            price_id = self.create(cr,
                                   uid, {
                                       'real_time_accounting': True,
                                       'recursive': True
                                   },
                                   context=context)
            try:
                if not prod_brw.cost_method == 'standard':
                    new = 'Ignored Because product is not set as Standard'
                else:
                    self.compute_from_bom(cr, uid, [price_id], context=context)
                    new = prod_brw.standard_price
            except Exception as msg:  # pylint: disable=W0703
                new = msg

            context['message'] = message % dict(old=old, new=new)
            self._post_message(cr, uid, ids, context=context)
        # /!\ TODO: Write log for products that were ignored
        return True
Exemple #41
0
    def do_merge(self, remove_empty_invoice_lines=True):
        def make_key(br, fields):
            list_key = []
            for field in fields:
                field_val = getattr(br, field)
                if field in ('product_id', 'account_id'):
                    if not field_val:
                        field_val = False
                if (isinstance(field_val, browse_record)
                        and field != 'invoice_line_tax_ids'
                        and field != 'sale_line_ids'):
                    field_val = field_val.id
                elif isinstance(field_val, browse_null):
                    field_val = False
                elif (isinstance(field_val, list)
                      or field == 'invoice_line_tax_ids'
                      or field == 'sale_line_ids'):
                    field_val = ((6, 0, tuple([v.id for v in field_val])), )
                list_key.append((field, field_val))
            list_key.sort()
            return tuple(list_key)

        new_invoices = {}
        draft_invoices = [
            invoice for invoice in self if invoice.state == 'draft'
        ]
        seen_origins = {}
        seen_client_refs = {}

        for account_invoice in draft_invoices:
            invoice_key = make_key(account_invoice,
                                   self._get_invoice_key_cols())
            new_invoice = new_invoices.setdefault(invoice_key, ({}, []))
            new_invoice[1].append(account_invoice.id)
            invoice_infos = new_invoice[0]
            if not invoice_infos:
                invoice_infos.update(
                    self._get_first_invoice_fields(account_invoice))

            for invoice_line in account_invoice.invoice_line_ids:
                cols = self._get_invoice_line_key_cols()
                line_key = make_key(invoice_line, cols)
                o_line = invoice_infos['invoice_line_ids'].setdefault(
                    line_key, {})
                if o_line:
                    o_line['quantity'] += invoice_line.quantity
                else:
                    o_line['quantity'] = invoice_line.quantity

        allinvoices = []
        allnewinvoices = []
        invoices_info = {}
        qty_prec = self.env['decimal.precision'].precision_get(
            'Product Unit of Measure')
        for invoice_key, (invoice_data, old_ids) in new_invoices.iteritems():
            if len(old_ids) < 2:
                allinvoices += (old_ids or [])
                continue
            for key, value in invoice_data['invoice_line_ids'].iteritems():
                value.update(dict(key))
            if remove_empty_invoice_lines:
                invoice_data['invoice_line_ids'] = [
                    (0, 0, value)
                    for value in invoice_data['invoice_line_ids'].itervalues()
                    if not float_is_zero(value['quantity'],
                                         precision_digits=qty_prec)
                ]
            else:
                invoice_data['invoice_line_ids'] = [
                    (0, 0, value)
                    for value in invoice_data['invoice_line_ids'].itervalues()
                ]

            newinvoice = self.with_context(is_merge=True).create(invoice_data)
            invoices_info.update({newinvoice.id: old_ids})
            allinvoices.append(newinvoice.id)
            allnewinvoices.append(newinvoice)

            for old_id in old_ids:
                old_invoice_id = self.sudo().browse(old_id)
                old_invoice_id.sudo().action_invoice_cancel()

        for new_invoice in allnewinvoices:
            new_invoice.compute_taxes()
        return invoices_info
Exemple #42
0
 def action_produce(self,
                    production_id,
                    production_qty,
                    production_mode,
                    wiz=False):
     stock_move_obj = self.env['stock.move']
     uom_obj = self.env['product.uom']
     production = self.browse(production_id)
     production_qty_uom = uom_obj._compute_qty(
         production.product_uom.id, production_qty,
         production.product_id.uom_id.id)
     precision = self.env['decimal.precision'].precision_get(
         'Product Unit of Measure')
     main_production_move = False
     default_mode = self._context.get('default_mode', False)
     if production_mode == 'produce':  # New Case: Produce Only
         produced_products = {}
         for produced_product in production.move_created_ids2:
             if produced_product.scrapped:
                 continue
             if not produced_products.get(produced_product.product_id.id,
                                          False):
                 produced_products[produced_product.product_id.id] = 0
             produced_products[produced_product.product_id.
                               id] += produced_product.product_qty
         for produce_product in production.move_created_ids:
             subproduct_factor = self._get_subproduct_factor(
                 production.id, produce_product.id)
             lot_id = wiz and wiz.lot_id.id or False
             qty = min(subproduct_factor * production_qty_uom,
                       produce_product.product_qty
                       )  # Needed when producing more than maximum quantity
             new_moves = produce_product.action_consume(
                 qty,
                 location_id=produce_product.location_id.id,
                 restrict_lot_id=lot_id)
             stock_move_obj.browse(new_moves).write(
                 {'production_id': production_id})
             remaining_qty = subproduct_factor * production_qty_uom - qty
             if not float_is_zero(remaining_qty,
                                  precision_digits=precision):
                 # In case you need to make more than planned
                 # consumed more in wizard than previously planned
                 extra_move_id = produce_product.copy(
                     default={
                         'product_uom_qty': remaining_qty,
                         'production_id': production_id
                     })
                 extra_move_id.action_confirm()
                 extra_move_id.action_done()
             if produce_product.product_id == production.product_id:
                 main_production_move = produce_product.id
         if default_mode != 'consume' and not production.move_created_ids:
             production.signal_workflow('button_finished_validated')
     else:
         if not main_production_move:
             main_production_move = production.move_created_ids2 and production.move_created_ids2[
                 0].id
         # Añadimos al contexto 'main_production_move'
         # para poder escribirlo en el write y en el action_consume()
         self = self.with_context(main_production_move=main_production_move)
         res = super(MrpProduction, self).action_produce(production_id,
                                                         production_qty,
                                                         production_mode,
                                                         wiz=wiz)
         if default_mode != 'consume' and not production.move_created_ids:
             production.signal_workflow('button_finished_validated')
         if default_mode == 'consume':
             # Custom behaivor, set closed state
             production.signal_workflow('button_validated_closed')
     return True
Exemple #43
0
    def action_invoice_create(self, grouped=False, final=False):
        """
        Create the invoice associated to the SO.
        :param grouped: if True, invoices are grouped by SO id. If False, invoices are grouped by
                        (partner_invoice_id, currency)
        :param final: if True, refunds will be generated if necessary
        :returns: list of created invoices
        """
        inv_obj = self.env['account.invoice']
        precision = self.env['decimal.precision'].precision_get(
            'Product Unit of Measure')
        invoices = {}

        for order in self:
            group_key = order.id if grouped else (order.partner_invoice_id.id,
                                                  order.currency_id.id)
            for line in order.actesmedicaux_lines.sorted(
                    key=lambda l: l.qty_to_invoice < 0):
                if float_is_zero(line.qty_to_invoice,
                                 precision_digits=precision):
                    continue
                if group_key not in invoices:
                    inv_data = order._prepare_invoice()
                    invoice = inv_obj.create(inv_data)
                    invoices[group_key] = invoice
                elif group_key in invoices:
                    vals = {}
                    if order.name not in invoices[group_key].origin.split(
                            ', '):
                        vals['origin'] = invoices[
                            group_key].origin + ', ' + order.name
                    if order.client_order_ref and order.client_order_ref not in invoices[
                            group_key].name.split(', '):
                        vals['name'] = invoices[
                            group_key].name + ', ' + order.client_order_ref
                    invoices[group_key].write(vals)
                if line.qty_to_invoice > 0:
                    line.invoice_line_create(invoices[group_key].id,
                                             line.qty_to_invoice)
                elif line.qty_to_invoice < 0 and final:
                    line.invoice_line_create(invoices[group_key].id,
                                             line.qty_to_invoice)

        if not invoices:
            raise UserError(_('There is no invoicable line.'))

        for invoice in invoices.values():
            if not invoice.invoice_line_ids:
                raise UserError(_('There is no invoicable line.'))
            # If invoice is negative, do a refund invoice instead
            if invoice.amount_untaxed < 0:
                invoice.type = 'out_refund'
                for line in invoice.invoice_line_ids:
                    line.quantity = -line.quantity
            # Use additional field helper function (for account extensions)
            for line in invoice.invoice_line_ids:
                line._set_additional_fields(invoice)
            # Necessary to force computation of taxes. In account_invoice, they are triggered
            # by onchanges, which are not triggered when doing a create.
            invoice.compute_taxes()

        return [inv.id for inv in invoices.values()]
Exemple #44
0
    def _process_order(self, cr, uid, order, context=None):
        session = self.pool.get('pos.session').browse(cr,
                                                      uid,
                                                      order['pos_session_id'],
                                                      context=context)

        if session.state == 'closing_control' or session.state == 'closed':
            session_id = self._get_valid_session(cr,
                                                 uid,
                                                 order,
                                                 context=context)
            session = self.pool.get('pos.session').browse(cr,
                                                          uid,
                                                          session_id,
                                                          context=context)
            order['pos_session_id'] = session_id

        order_id = self.create(
            cr, uid, self._order_fields(cr, uid, order, context=context),
            context)
        journal_ids = set()
        for payments in order['statement_ids']:
            self.add_payment(cr,
                             uid,
                             order_id,
                             self._payment_fields(cr,
                                                  uid,
                                                  payments[2],
                                                  context=context),
                             context=context)
            journal_ids.add(payments[2]['journal_id'])

        if session.sequence_number <= order['sequence_number']:
            session.write({'sequence_number': order['sequence_number'] + 1})
            session.refresh()

        if not float_is_zero(
                order['amount_return'],
                self.pool.get('decimal.precision').precision_get(
                    cr, uid, 'Account')):
            # cash_journal = session.cash_journal_id.id
            cash_journal = False
            if session.config_id.journal_negativo_id:
                cash_journal = session.config_id.journal_negativo_id.id
            if not cash_journal:
                # Select for change one of the cash journals used in this payment
                cash_journal_ids = self.pool['account.journal'].search(
                    cr,
                    uid, [
                        ('type', '=', 'cash'),
                        ('id', 'in', list(journal_ids)),
                    ],
                    limit=1,
                    context=context)
                if not cash_journal_ids:
                    # If none, select for change one of the cash journals of the POS
                    # This is used for example when a customer pays by credit card
                    # an amount higher than total amount of the order and gets cash back
                    cash_journal_ids = [
                        statement.journal_id.id
                        for statement in session.statement_ids
                        if statement.journal_id.type == 'cash'
                    ]
                    if not cash_journal_ids:
                        raise osv.except_osv(
                            _('error!'),
                            _("No cash statement found for this session. Unable to record returned cash."
                              ))
                cash_journal = cash_journal_ids[0]
            self.add_payment(
                cr,
                uid,
                order_id, {
                    'amount': -order['amount_return'],
                    'payment_date': time.strftime('%Y-%m-%d %H:%M:%S'),
                    'payment_name': _('return'),
                    'journal': cash_journal,
                },
                context=context)
        return order_id
    def post_cost(self):
        move_pool = self.env['account.move']
        # period_pool = self.env['account.period']
        precision = self.env['decimal.precision'].precision_get('Account')
        timenow = fields.Date.today()

        for cost in self:
            line_ids = []
            debit_sum = 0.0
            credit_sum = 0.0
            # search_periods = period_pool.find(cost.date)
            # period_id = search_periods[0]
            period_id = False

            default_partner_id = cost.vendor_id.id
            name = _('%s cost of %s') % (cost.cost_subtype_id.name.capitalize(), cost.vehicle_id.name)
            move = {
                'narration': name,
                'date': timenow,
                'ref': cost.ref,
                'journal_id': cost.cost_subtype_id.journal_id,
                'period_id': period_id,
            }
            amt = cost.amount
            if float_is_zero(amt, precision_digits=precision):
                return
            partner_id = default_partner_id
            account_info = cost.get_account_info()
            debit_account_id = account_info['account_debit']
            credit_account_id = account_info['account_credit']
            analytic_account_id = account_info['analytic_account_id']
            journal_id = account_info['journal_id']

            if debit_account_id:
                debit_line = (0, 0, {
                    'name': cost.name,
                    'date': timenow,
                    'partner_id': partner_id or False,
                    'account_id': debit_account_id,
                    'journal_id': journal_id.id,
                    'period_id': period_id,
                    'debit': amt > 0.0 and amt or 0.0,
                    'credit': amt < 0.0 and -amt or 0.0,
                    'analytic_account_id': analytic_account_id or False,
                })
                line_ids.append(debit_line)
                debit_sum += debit_line[2]['debit'] - debit_line[2]['credit']

            if credit_account_id:
                credit_line = (0, 0, {
                    'name': cost.name,
                    'date': timenow,
                    'partner_id': partner_id or False,
                    'account_id': debit_account_id,
                    'journal_id': journal_id.id,
                    'period_id': period_id,
                    'debit': amt < 0.0 and -amt or 0.0,
                    'credit': amt > 0.0 and amt or 0.0,
                    'analytic_account_id': analytic_account_id or False,
                })
                line_ids.append(credit_line)
                credit_sum += credit_line[2]['credit'] - credit_line[2]['debit']

            if float_compare(credit_sum, debit_sum, precision_digits=precision) == -1:
                acc_id = journal_id.default_credit_account_id.id
                if not acc_id:
                    raise UserError(_('The Expense Journal "%s" has not properly configured the Credit Account!') % (journal_id.name))
                adjust_credit = (0, 0, {
                    'name': _('Adjustment Entry'),
                    'date': timenow,
                    'partner_id': False,
                    'account_id': acc_id,
                    'journal_id': journal_id.id,
                    'period_id': period_id,
                    'debit': 0.0,
                    'credit': debit_sum - credit_sum,
                })
                line_ids.append(adjust_credit)

            elif float_compare(debit_sum, credit_sum, precision_digits=precision) == -1:
                acc_id = cost.journal_id.default_debit_account_id.id
                if not acc_id:
                    raise UserError(_('Configuration Error!'), _('The Expense Journal "%s" has not properly configured the Debit Account!') % (cost.journal_id.name))
                adjust_debit = (0, 0, {
                    'name': _('Adjustment Entry'),
                    'date': timenow,
                    'partner_id': False,
                    'account_id': acc_id,
                    'journal_id': journal_id.id,
                    'period_id': period_id,
                    'debit': credit_sum - debit_sum,
                    'credit': 0.0,
                })
                line_ids.append(adjust_debit)

            move.update({'line_id': line_ids})
            move = move_pool.create(move)
            cost.move_id = move
            if journal_id.entry_posted:
                move.post()
            return move
    def _get_partner_move_lines(self, form, account_type, date_from, target_move):
        res = []
        self.total_account = []
        cr = self.env.cr
        user_company = self.env.user.company_id.id
        move_state = ['draft', 'posted']
        if target_move == 'posted':
            move_state = ['posted']
        arg_list = (tuple(move_state), tuple(account_type))
        #build the reconciliation clause to see what partner needs to be printed
        reconciliation_clause = '(l.reconciled IS FALSE)'
        cr.execute('SELECT debit_move_id, credit_move_id FROM account_partial_reconcile where create_date > %s', (date_from,))
        reconciled_after_date = []
        for row in cr.fetchall():
            reconciled_after_date += [row[0], row[1]]
        if reconciled_after_date:
            reconciliation_clause = '(l.reconciled IS FALSE OR l.id IN %s)'
            arg_list += (tuple(reconciled_after_date),)
        arg_list += (date_from, user_company)
        query = '''
            SELECT DISTINCT res_partner.id AS id, res_partner.name AS name, UPPER(res_partner.name) AS uppername
            FROM res_partner,account_move_line AS l, account_account, account_move am
            WHERE (l.account_id = account_account.id)
                AND (l.move_id = am.id)
                AND (am.state IN %s)
                AND (account_account.internal_type IN %s)
                AND ''' + reconciliation_clause + '''
                AND (l.partner_id = res_partner.id)
                AND (l.date <= %s)
                AND l.company_id = %s
            ORDER BY UPPER(res_partner.name)'''
        cr.execute(query, arg_list)

        partners = cr.dictfetchall()
        # put a total of 0
        for i in range(7):
            self.total_account.append(0)

        # Build a string like (1,2,3) for easy use in SQL query
        partner_ids = [partner['id'] for partner in partners]
        if not partner_ids:
            return []

        # This dictionary will store the not due amount of all partners
        future_past = {}
        query = '''SELECT l.id
                FROM account_move_line AS l, account_account, account_move am
                WHERE (l.account_id = account_account.id) AND (l.move_id = am.id)
                    AND (am.state IN %s)
                    AND (account_account.internal_type IN %s)
                    AND (COALESCE(l.date_maturity,l.date) > %s)\
                    AND (l.partner_id IN %s)
                AND (l.date <= %s)
                AND l.company_id = %s'''
        cr.execute(query, (tuple(move_state), tuple(account_type), date_from, tuple(partner_ids), date_from, user_company))
        aml_ids = cr.fetchall()
        aml_ids = aml_ids and [x[0] for x in aml_ids] or []
        for line in self.env['account.move.line'].browse(aml_ids):
            if line.partner_id.id not in future_past:
                future_past[line.partner_id.id] = 0.0
            line_amount = line.balance
            if line.balance == 0:
                continue
            for partial_line in line.matched_debit_ids:
                if partial_line.create_date[:10] <= date_from:
                    line_amount += partial_line.amount
            for partial_line in line.matched_credit_ids:
                if partial_line.create_date[:10] <= date_from:
                    line_amount -= partial_line.amount
            future_past[line.partner_id.id] += line_amount

        # Use one query per period and store results in history (a list variable)
        # Each history will contain: history[1] = {'<partner_id>': <partner_debit-credit>}
        history = []
        for i in range(5):
            args_list = (tuple(move_state), tuple(account_type), tuple(partner_ids),)
            dates_query = '(COALESCE(l.date_maturity,l.date)'

            if form[str(i)]['start'] and form[str(i)]['stop']:
                dates_query += ' BETWEEN %s AND %s)'
                args_list += (form[str(i)]['start'], form[str(i)]['stop'])
            elif form[str(i)]['start']:
                dates_query += ' >= %s)'
                args_list += (form[str(i)]['start'],)
            else:
                dates_query += ' <= %s)'
                args_list += (form[str(i)]['stop'],)
            args_list += (date_from, user_company)

            query = '''SELECT l.id
                    FROM account_move_line AS l, account_account, account_move am
                    WHERE (l.account_id = account_account.id) AND (l.move_id = am.id)
                        AND (am.state IN %s)
                        AND (account_account.internal_type IN %s)
                        AND (l.partner_id IN %s)
                        AND ''' + dates_query + '''
                    AND (l.date <= %s)
                    AND l.company_id = %s'''
            cr.execute(query, args_list)
            partners_amount = {}
            aml_ids = cr.fetchall()
            aml_ids = aml_ids and [x[0] for x in aml_ids] or []
            for line in self.env['account.move.line'].browse(aml_ids):
                if line.partner_id.id not in partners_amount:
                    partners_amount[line.partner_id.id] = 0.0
                line_amount = line.balance
                if line.balance == 0:
                    continue
                for partial_line in line.matched_debit_ids:
                    if partial_line.create_date[:10] <= date_from:
                        line_amount += partial_line.amount
                for partial_line in line.matched_credit_ids:
                    if partial_line.create_date[:10] <= date_from:
                        line_amount -= partial_line.amount

                partners_amount[line.partner_id.id] += line_amount
            history.append(partners_amount)

        for partner in partners:
            at_least_one_amount = False
            values = {}
            # Query here is replaced by one query which gets the all the partners their 'after' value
            after = False
            if partner['id'] in future_past:  # Making sure this partner actually was found by the query
                after = [future_past[partner['id']]]

            self.total_account[6] = self.total_account[6] + (after and after[0] or 0.0)
            values['direction'] = after and after[0] or 0.0
            if not float_is_zero(values['direction'], precision_rounding=self.env.user.company_id.currency_id.rounding):
                at_least_one_amount = True

            for i in range(5):
                during = False
                if partner['id'] in history[i]:
                    during = [history[i][partner['id']]]
                # Adding counter
                self.total_account[(i)] = self.total_account[(i)] + (during and during[0] or 0)
                values[str(i)] = during and during[0] or 0.0
                if not float_is_zero(values[str(i)], precision_rounding=self.env.user.company_id.currency_id.rounding):
                    at_least_one_amount = True
            values['total'] = sum([values['direction']] + [values[str(i)] for i in range(5)])
            ## Add for total
            self.total_account[(i + 1)] += values['total']
            values['name'] = partner['name']

            if at_least_one_amount:
                res.append(values)

        total = 0.0
        totals = {}
        for r in res:
            total += float(r['total'] or 0.0)
            for i in range(5) + ['direction']:
                totals.setdefault(str(i), 0.0)
                totals[str(i)] += float(r[str(i)] or 0.0)
        return res
Exemple #47
0
 def _create_closing_move(self,
                          cr,
                          uid,
                          account_mapping_ids,
                          period_ids,
                          description,
                          date,
                          period_id,
                          journal_id,
                          company_id,
                          fiscalyear_id,
                          context=None):
     """Create a closing move with the given data, provided by another
     method.
     """
     if context is None:
         context = {}
     move_lines = []
     dest_accounts_totals = {}
     ctx = context.copy()
     ctx.update({
         'fiscalyear': fiscalyear_id,
         'periods': period_ids,
         'company_id': company_id
     })
     account_obj = self.pool['account.account']
     move_line_obj = self.pool['account.move.line']
     decimal_precision_obj = self.pool['decimal.precision']
     precision = decimal_precision_obj.precision_get(cr, uid, 'Account')
     # For each (parent) account in the mapping list
     for account_map in account_mapping_ids:
         # Init (if needed) the dictionary that will store the totals for
         # the dest accounts
         if account_map.dest_account_id and not \
                 dest_accounts_totals.get(account_map.dest_account_id.id):
             dest_accounts_totals[account_map.dest_account_id.id] = 0
         # Find its children accounts (recursively)
         # FIXME: _get_children_and_consol is a protected member of
         # account_account,
         # but the OpenERP code base uses it like this :(
         child_ids = account_obj._get_children_and_consol(
             cr, uid, [account_map.source_account_id.id], ctx)
         # For each children account. (Notice the context filter! the
         # computed balanced is based on this filter)
         for account in account_obj.browse(cr, uid, child_ids, ctx):
             # Check if the children account needs to (and can) be closed
             if account.type == 'view':
                 continue
             if account.user_type.close_method == 'balance':
                 # Compute the balance for the account (uses the
                 # previous browse context filter)
                 balance = account.balance
                 # Check if the balance is greater than the limit
                 if not float_is_zero(balance, precision_digits=precision):
                     # Add a new line to the move
                     move_lines.append({
                         'account_id': account.id,
                         'debit': balance < 0 and -balance,
                         'credit': balance > 0 and balance,
                         'name': description,
                         'date': date,
                         'partner_id': False,
                         'period_id': period_id,
                         'journal_id': journal_id,
                     })
                     # Update the dest account total (with the inverse
                     # of the balance)
                     if account_map.dest_account_id:
                         dest_id = account_map.dest_account_id.id
                         dest_accounts_totals[dest_id] -= balance
             elif account.user_type.close_method == 'unreconciled':
                 found_lines = move_line_obj.search(cr, uid, [
                     ('period_id', 'in', period_ids),
                     ('account_id', '=', account.id),
                     ('company_id', '=', company_id),
                 ])
                 lines_by_partner = {}
                 for line in move_line_obj.browse(cr, uid, found_lines):
                     partner_id = line.partner_id.id
                     balance = line.debit - line.credit
                     lines_by_partner[partner_id] = (
                         lines_by_partner.get(partner_id, 0.0) + balance)
                 for partner_id in lines_by_partner.keys():
                     balance = lines_by_partner[partner_id]
                     if not float_is_zero(balance,
                                          precision_digits=precision):
                         move_lines.append({
                             'account_id': account.id,
                             'debit': balance < 0 and -balance,
                             'credit': balance > 0 and balance,
                             'name': description,
                             'date': date,
                             'period_id': period_id,
                             'journal_id': journal_id,
                             'partner_id': partner_id,
                         })
                     # Update the dest account total (with the inverse
                     # of the balance)
                     if account_map.dest_account_id:
                         dest_id = account_map.dest_account_id.id
                         dest_accounts_totals[dest_id] -= balance
             elif account.user_type.close_method == 'detail':
                 raise orm.except_orm(
                     _('UserError'),
                     _("Account type closing method is not supported"))
             else:
                 # Account type has no closing method or method is not
                 # listed
                 continue
     # Add the dest lines
     for dest_account_id in dest_accounts_totals.keys():
         balance = dest_accounts_totals[dest_account_id]
         move_lines.append({
             'account_id': dest_account_id,
             'debit': balance < 0 and -balance,
             'credit': balance > 0 and balance,
             'name': description,
             'date': date,
             'partner_id': False,
             'period_id': period_id,
             'journal_id': journal_id,
         })
     # Finally create the account move with all the lines (if needed)
     if len(move_lines):
         move_id = self.pool.get('account.move').create(
             cr,
             uid, {
                 'line_id': map(lambda x: (0, 0, x), move_lines),
                 'ref': description,
                 'date': date,
                 'period_id': period_id,
                 'journal_id': journal_id,
             },
             context={})
     else:
         move_id = False
     return move_id
Exemple #48
0
    def _process_order(self, order):
        # initialization
        pos_line_obj = self.env['pos.order.line']
        move_obj = self.env['stock.move']
        picking_obj = self.env['stock.picking']
        stock_imm_tra_obj = self.env['stock.immediate.transfer']
        draft_order_id = order.get('old_order_id')
        picking_type_id = False
        picking_id_cust = False
        picking_id_rev = False
        if order.get('draft_order'):
            if not draft_order_id:
                order.pop('draft_order')
                order_id = self.create(self._order_fields(order))
                return order_id
            else:
                order_id = draft_order_id
                pos_line_ids = pos_line_obj.search([('order_id', '=', order_id)
                                                    ])
                if pos_line_ids:
                    pos_line_obj.unlink(pos_line_ids)
                self.write([order_id], {
                    'lines': order['lines'],
                    'partner_id': order.get('partner_id')
                })
                return order_id

        if not order.get('draft_order') and draft_order_id:
            order_id = draft_order_id
            order_obj = self.browse(order_id)
            pos_line_ids = pos_line_obj.search([('order_id', '=', order_id)])
            if pos_line_ids:
                if not order.get('cancel_order'):
                    for line_id in pos_line_ids:
                        line_id.unlink()
            temp = order.copy()
            temp.pop('statement_ids', None)
            temp.pop('name', None)
            temp.update({'date_order': order.get('creation_date')})
            warehouse_id = self.env['stock.warehouse'].search([
                ('lot_stock_id', '=', order_obj.config_id.stock_location_id.id)
            ],
                                                              limit=1)
            location_dest_id, supplierloc = self.env[
                'stock.warehouse']._get_partner_locations()
            if warehouse_id:
                picking_type_id = self.env['stock.picking.type'].search([
                    ('warehouse_id', '=', warehouse_id.id),
                    ('code', '=', 'internal')
                ])
            for line in order.get('lines'):
                prod_id = self.env['product.product'].browse(
                    line[2].get('product_id'))
                prod_dict = line[2]
                if prod_id.type != 'service' and prod_dict and prod_dict.get(
                        'cancel_item'):
                    # customer delivery order
                    picking_type_out = self.env['stock.picking.type'].search(
                        [('warehouse_id', '=',
                          order_obj.picking_id.picking_type_id.warehouse_id.id
                          ), ('code', '=', 'outgoing')],
                        limit=1)
                    if picking_type_out:
                        picking_id_cust = picking_obj.create({
                            'name':
                            picking_type_out.sequence_id.next_by_id(),
                            'picking_type_id':
                            picking_type_out.id,
                            'location_id':
                            order_obj.config_id.reserve_stock_location_id.id,
                            'location_dest_id':
                            location_dest_id.id,
                            'state':
                            'draft',
                            'origin':
                            order_obj.name
                        })
                    if order_obj.picking_id:
                        # unreserve order
                        picking_id_rev = picking_obj.create({
                            'name':
                            picking_type_out.sequence_id.next_by_id(),
                            'picking_type_id':
                            order_obj.picking_id.picking_type_id.id,
                            'location_id':
                            order_obj.config_id.reserve_stock_location_id.id,
                            'location_dest_id':
                            order_obj.config_id.stock_location_id.id,
                            'state':
                            'draft',
                            'origin':
                            order_obj.name
                        })
                        if prod_dict.get(
                                'consider_qty'
                        ) and not order_obj.order_status == 'partial' and not order.get(
                                'reserved'):
                            move_obj.create({
                                'product_id':
                                prod_id.id,
                                'name':
                                prod_id.name,
                                'product_uom_qty':
                                prod_dict.get('consider_qty'),
                                'location_id':
                                order_obj.config_id.reserve_stock_location_id.
                                id,
                                'location_dest_id':
                                location_dest_id.id,
                                'product_uom':
                                prod_id.uom_id.id,
                                'origin':
                                order_obj.name,
                                'picking_id':
                                picking_id_cust.id
                            })
                        if prod_dict.get('cancel_qty'):
                            move_obj.create({
                                'product_id':
                                prod_id.id,
                                'name':
                                prod_id.name,
                                'product_uom_qty':
                                abs(prod_dict.get('cancel_qty')),
                                'location_id':
                                order_obj.config_id.reserve_stock_location_id.
                                id,
                                'location_dest_id':
                                order_obj.config_id.stock_location_id.id,
                                'product_uom':
                                prod_id.uom_id.id,
                                'origin':
                                order_obj.name,
                                'picking_id':
                                picking_id_rev.id
                            })
            if picking_id_cust and picking_id_cust.move_lines:
                picking_id_cust.action_confirm()
                picking_id_cust.action_assign()
                picking_id_cust.button_validate()
                stock_transfer_id = stock_imm_tra_obj.search(
                    [('pick_ids', '=', picking_id_cust.id)],
                    limit=1).process()
                if stock_transfer_id:
                    stock_transfer_id.process()
                order_obj.with_context({
                    'out_order': True
                }).write({
                    'picking_id': picking_id_cust.id,
                    'unreserved': True
                })
            elif picking_id_cust:
                picking_id_cust.unlink()
            if picking_id_rev and picking_id_rev.move_lines:
                picking_id_rev.action_confirm()
                picking_id_rev.action_assign()
                picking_id_rev.button_validate()
                stock_transfer_id = stock_imm_tra_obj.search(
                    [('pick_ids', '=', picking_id_rev.id)], limit=1).process()
                if stock_transfer_id:
                    stock_transfer_id.process()
                order_obj.with_context({
                    'out_order': True
                }).write({
                    'picking_id': picking_id_rev.id,
                    'unreserved': True
                })
            elif picking_id_rev:
                picking_id_rev.unlink()
            total_price = 0.00
            for line in temp.get('lines'):
                linedict = line[2]
                if order_obj.session_id.config_id.prod_for_payment.id == linedict.get(
                        'product_id'):
                    temp.get('lines').remove(line)
                if order_obj.session_id.config_id.refund_amount_product_id.id == linedict.get(
                        'product_id'):
                    temp.get('lines').remove(line)
            total_price += sum([
                line[2].get('price_subtotal_incl')
                for line in temp.get('lines')
            ])
            temp['amount_total'] = total_price
            order_obj.write(temp)
            for payments in order['statement_ids']:
                order_obj.with_context({
                    'from_pos': True
                }).add_payment(self._payment_fields(payments[2]))
            session = self.env['pos.session'].browse(order['pos_session_id'])
            if session.sequence_number <= order['sequence_number']:
                session.write(
                    {'sequence_number': order['sequence_number'] + 1})
                session.refresh()
            if not float_is_zero(
                    order['amount_return'], self.env['decimal.precision'].
                    precision_get('Account')) or order['cancel_order']:
                cash_journal = session.cash_journal_id
                if not cash_journal:
                    cash_journal_ids = session.statement_ids.filtered(
                        lambda st: st.journal_id.type == 'cash')
                    if not len(cash_journal_ids):
                        raise Warning(
                            _('error!'),
                            _("No cash statement found for this session. Unable to record returned cash."
                              ))
                    cash_journal = cash_journal_ids[0].journal_id
                order_obj.with_context({
                    'from_pos': True
                }).add_payment({
                    'amount':
                    -order['amount_return'],
                    'payment_date':
                    time.strftime('%Y-%m-%d %H:%M:%S'),
                    'payment_name':
                    _('return'),
                    'journal':
                    cash_journal.id,
                })
            return order_obj
        if not order.get('draft_order') and not draft_order_id:
            order_id = super(pos_order, self)._process_order(order)
            if order_id.reserved:
                order_id.do_internal_transfer()
            return order_id
Exemple #49
0
    def action_produce(self,
                       cr,
                       uid,
                       production_id,
                       production_qty,
                       production_mode,
                       wiz=False,
                       context=None):
        """ To produce final product based on production mode (consume/consume&produce).
        If Production mode is consume, all stock move lines of raw materials will be done/consumed.
        If Production mode is consume & produce, all stock move lines of raw materials will be done/consumed
        and stock move lines of final product will be also done/produced.
        @param production_id: the ID of mrp.production object
        @param production_qty: specify qty to produce in the uom of the production order
        @param production_mode: specify production mode (consume/consume&produce).
        @param wiz: the mrp produce product wizard, which will tell the amount of consumed products needed
        @return: True
        """
        stock_mov_obj = self.pool.get('stock.move')
        uom_obj = self.pool.get("product.uom")
        production = self.browse(cr, uid, production_id, context=context)
        production_qty_uom = uom_obj._compute_qty(
            cr, uid, production.product_uom.id, production_qty,
            production.product_id.uom_id.id)
        precision = self.pool['decimal.precision'].precision_get(
            cr, uid, 'Product Unit of Measure')

        main_production_move = False
        if production_mode == 'consume_produce':
            for produce_product in production.move_created_ids:
                if produce_product.product_id.id == production.product_id.id:
                    main_production_move = produce_product.id

        total_consume_moves = set()
        if production_mode in ['consume', 'consume_produce']:
            if wiz:
                consume_lines = []
                for cons in wiz.consume_lines:
                    consume_lines.append({
                        'product_id': cons.product_id.id,
                        'lot_id': cons.lot_id.id,
                        'product_qty': cons.product_qty
                    })
            else:
                consume_lines = self._calculate_qty(cr,
                                                    uid,
                                                    production,
                                                    production_qty_uom,
                                                    context=context)
            for consume in consume_lines:
                remaining_qty = consume['product_qty']
                for raw_material_line in production.move_lines:
                    if raw_material_line.state in ('done', 'cancel'):
                        continue
                    if remaining_qty <= 0:
                        break
                    if consume['product_id'] != raw_material_line.product_id.id:
                        continue
                    consumed_qty = min(remaining_qty,
                                       raw_material_line.product_qty)
                    stock_mov_obj.action_consume(
                        cr,
                        uid, [raw_material_line.id],
                        consumed_qty,
                        raw_material_line.location_id.id,
                        restrict_lot_id=consume['lot_id'],
                        consumed_for=main_production_move,
                        context=context)
                    total_consume_moves.add(raw_material_line.id)
                    remaining_qty -= consumed_qty
                if not float_is_zero(remaining_qty,
                                     precision_digits=precision):
                    # consumed more in wizard than previously planned
                    product = self.pool.get('product.product').browse(
                        cr, uid, consume['product_id'], context=context)
                    extra_move_id = self._make_consume_line_from_data(
                        cr,
                        uid,
                        production,
                        product,
                        product.uom_id.id,
                        remaining_qty,
                        context=context)
                    stock_mov_obj.write(
                        cr,
                        uid, [extra_move_id], {
                            'restrict_lot_id': consume['lot_id'],
                            'consumed_for': main_production_move
                        },
                        context=context)
                    stock_mov_obj.action_done(cr,
                                              uid, [extra_move_id],
                                              context=context)
                    total_consume_moves.add(extra_move_id)

        if production_mode == 'consume_produce':
            # add production lines that have already been consumed since the last 'consume & produce'
            last_production_date = production.move_created_ids2 and max(
                production.move_created_ids2.mapped('date')) or False
            already_consumed_lines = production.move_lines2.filtered(
                lambda l: l.date > last_production_date)
            total_consume_moves = total_consume_moves.union(
                already_consumed_lines.ids)

            price_unit = 0
            for produce_product in production.move_created_ids:
                is_main_product = (
                    produce_product.product_id.id == production.product_id.id
                ) and production.product_id.cost_method == 'real'
                if is_main_product:
                    total_cost = self._calculate_total_cost(
                        cr, uid, list(total_consume_moves), context=context)
                    production_cost = self._calculate_workcenter_cost(
                        cr, uid, production_id, context=context)
                    price_unit = (total_cost +
                                  production_cost) / production_qty_uom

                subproduct_factor = self._get_subproduct_factor(
                    cr,
                    uid,
                    production.id,
                    produce_product.id,
                    context=context)
                lot_id = False
                if wiz:
                    lot_id = wiz.lot_id.id
                qty = min(subproduct_factor * production_qty_uom,
                          produce_product.product_qty
                          )  #Needed when producing more than maximum quantity

                # Verificamos si hay una línea de subproducto y si hay una diferencia.
                subproduct_diff = 0
                subproduct_line = self.pool.get('mrp.subproduct.produce.line')
                if produce_product.product_id != production.product_id:
                    subproduct_line = wiz.subproduct_created_ids.filtered(
                        lambda x: x.product_id == produce_product.product_id)
                    subproduct_qty = subproduct_line.product_uom_qty
                    if subproduct_qty > qty:
                        subproduct_diff = subproduct_qty - qty
                    else:
                        qty = subproduct_qty
                elif production_qty > produce_product.product_uom_qty:
                    subproduct_diff = production_qty - produce_product.product_uom_qty

                if is_main_product and price_unit:
                    stock_mov_obj.write(cr,
                                        uid, [produce_product.id],
                                        {'price_unit': price_unit},
                                        context=context)
                new_moves = stock_mov_obj.action_consume(
                    cr,
                    uid, [produce_product.id],
                    qty,
                    location_id=produce_product.location_id.id,
                    restrict_lot_id=lot_id,
                    context=context)
                stock_mov_obj.write(cr,
                                    uid,
                                    new_moves,
                                    {'production_id': production_id},
                                    context=context)

                remaining_qty = subproduct_diff

                remaining_qty = subproduct_diff
                if not float_is_zero(remaining_qty,
                                     precision_digits=precision):
                    # In case you need to make more than planned
                    # consumed more in wizard than previously planned
                    extra_move_id = stock_mov_obj.copy(cr,
                                                       uid,
                                                       produce_product.id,
                                                       default={
                                                           'product_uom_qty':
                                                           remaining_qty,
                                                           'production_id':
                                                           production_id
                                                       },
                                                       context=context)
                    if is_main_product:
                        stock_mov_obj.write(cr,
                                            uid, [extra_move_id],
                                            {'price_unit': price_unit},
                                            context=context)
                    stock_mov_obj.action_confirm(cr,
                                                 uid, [extra_move_id],
                                                 context=context)
                    stock_mov_obj.action_done(cr,
                                              uid, [extra_move_id],
                                              context=context)

        self.message_post(cr,
                          uid,
                          production_id,
                          body=_("%s produced") % self._description,
                          context=context)

        # Remove remaining products to consume if no more products to produce
        # Verificamos los valores pendientes de producción solamente contra el producto principal.

        main_product_remaining = production.move_created_ids.filtered(
            lambda x: x.product_id == production.product_id)
        if not main_product_remaining:
            if production.move_lines:
                stock_mov_obj.action_cancel(
                    cr,
                    uid, [x.id for x in production.move_lines],
                    context=context)
            if production.move_created_ids:
                stock_mov_obj.action_cancel(
                    cr,
                    uid, [x.id for x in production.move_created_ids],
                    context=context)

        self.signal_workflow(cr, uid, [production_id], 'button_produce_done')
        return True
    def _calc_price(
            self, cr, uid, bom, test=False, real_time_accounting=False,
            context=None):
        context = dict(context or {})
        price = 0
        uom_obj = self.pool.get("product.uom")
        tmpl_obj = self.pool.get('product.template')
        wizard_obj = self.pool.get("stock.change.standard.price")
        bom_obj = self.pool.get('mrp.bom')
        prod_obj = self.pool.get('product.product')
        user = self.pool.get('res.users').browse(cr, uid, uid, context)
        precision_id = self.pool.get('decimal.precision').precision_get(
            cr, uid, 'Account')
        model = 'product.product'

        def _get_sgmnt(prod_id):
            res = {}
            sum_sgmnt = 0.0
            for fieldname in SEGMENTATION_COST:
                fn_cost = getattr(prod_id, fieldname)
                sum_sgmnt += fn_cost
                res[fieldname] = fn_cost
            if not sum_sgmnt:
                res['material_cost'] = prod_id.standard_price
            return res

        def _bom_find(prod_id):
            if model == 'product.product':
                # if not look for template
                bom_id = bom_obj._bom_find(
                    cr, uid, product_id=prod_id, context=context)
                if bom_id:
                    return bom_id
                prod_id = prod_obj.browse(
                    cr, uid, prod_id, context=context).product_tmpl_id.id
            return bom_obj._bom_find(
                cr, uid, product_tmpl_id=prod_id, context=context)

        def _factor(factor, product_efficiency, product_rounding):
            factor = factor / (product_efficiency or 1.0)
            factor = _common.ceiling(factor, product_rounding)
            if factor < product_rounding:
                factor = product_rounding
            return factor

        factor = _factor(1.0, bom.product_efficiency, bom.product_rounding)

        sgmnt_dict = {}.fromkeys(SEGMENTATION_COST, 0.0)
        for sbom in bom.bom_line_ids:
            my_qty = sbom.product_qty / sbom.product_efficiency
            if sbom.attribute_value_ids:
                continue
            # No attribute_value_ids means the bom line is not variant
            # specific

            prod_costs_dict = {}.fromkeys(SEGMENTATION_COST, 0.0)
            product_id = sbom.product_id
            if product_id.cost_method == 'average':
                prod_costs_dict = _get_sgmnt(product_id)
            else:
                #  NOTE: Case when product is REAL or STANDARD
                if test and context['_calc_price_recursive']:
                    init_bom_id = _bom_find(product_id.id)
                    if init_bom_id:
                        prod_costs_dict['material_cost'] = self._calc_price(
                            cr, uid, bom_obj.browse(
                                cr, uid, init_bom_id, context=context),
                            test=test,
                            real_time_accounting=real_time_accounting,
                            context=context)
                    else:
                        prod_costs_dict = _get_sgmnt(product_id)
                else:
                    prod_costs_dict = _get_sgmnt(product_id)

            for fieldname in SEGMENTATION_COST:
                # NOTE: Is this price well Normalized
                if not prod_costs_dict[fieldname]:
                    continue
                price_sgmnt = uom_obj._compute_price(
                    cr, uid, product_id.uom_id.id,
                    prod_costs_dict[fieldname],
                    sbom.product_uom.id) * my_qty
                price += price_sgmnt
                sgmnt_dict[fieldname] += price_sgmnt

        if bom.routing_id:
            for wline in bom.routing_id.workcenter_lines:
                wc = wline.workcenter_id
                cycle = wline.cycle_nbr
                dd, mm = divmod(factor, wc.capacity_per_cycle)
                mult = (dd + (mm and 1.0 or 0.0))
                hour = float(
                    wline.hour_nbr * mult + (
                        (wc.time_start or 0.0) + (wc.time_stop or 0.0) +
                        cycle * (wc.time_cycle or 0.0)) * (
                            wc.time_efficiency or 1.0))
                routing_price = wc.costs_cycle * cycle + wc.costs_hour * hour
                routing_price = uom_obj._compute_price(
                    cr, uid, bom.product_uom.id, routing_price,
                    bom.product_id.uom_id.id)
                price += routing_price
                sgmnt_dict['production_cost'] += routing_price

        # Convert on product UoM quantities
        if price > 0:
            price = uom_obj._compute_price(
                cr, uid, bom.product_uom.id, price / bom.product_qty,
                bom.product_id.uom_id.id)

        if test:
            return price

        # NOTE: Instanciating BOM related product
        product_tmpl_id = tmpl_obj.browse(
            cr, uid, bom.product_tmpl_id.id, context=context)

        bottom_price_threshold = product_tmpl_id.company_id.\
            std_price_neg_threshold
        if not bottom_price_threshold:
            bottom_price_threshold = user.company_id.std_price_neg_threshold

        current_price = product_tmpl_id.standard_price
        diff = price - current_price
        computed_th = current_price and abs(diff * 100 / current_price) or 0.0

        if diff < 0 and current_price == 0:
            return price

        if float_is_zero(diff, precision_id) or \
                (current_price and diff < 0 and
                    computed_th > bottom_price_threshold):
            tmpl_obj.message_post(cr, uid, [product_tmpl_id.id],
                                  'Not Updated Cost, But Segments only.',
                                  'I cowardly did not update Standard new \n'
                                  'price less than old price \n'
                                  'new {new} old {old} \n'
                                  'Segments where written CHECK AFTERWARDS.'
                                  '{segments}'.
                                  format(old=current_price, new=price,
                                         segments=str(sgmnt_dict)))
            # Just writting segments to be consistent with segmentation
            # feature. TODO: A report should show differences.
            tmpl_obj.write(cr, uid, [product_tmpl_id.id], sgmnt_dict,
                           context=context)
            return price

        diff = product_tmpl_id.standard_price - price
        # Write standard price
        if product_tmpl_id.valuation == "real_time" and \
                real_time_accounting and diff:
            # Call wizard function here
            ctx = context.copy()
            ctx.update(
                {'active_id': product_tmpl_id.id,
                 'active_model': 'product.template'})
            wizard_id = wizard_obj.create(
                cr, uid, {'new_price': price}, context=ctx)
            wizard_obj.change_price(cr, uid, [wizard_id], context=ctx)
        else:
            tmpl_obj.write(
                cr, uid, [product_tmpl_id.id], {'standard_price': price},
                context=context)
        tmpl_obj.write(
            cr, uid, [product_tmpl_id.id], sgmnt_dict, context=context)

        return price
    def action_invoice_create(self,
                              grouped=False,
                              final=False,
                              split_invoice=False):
        """
		Create the invoice associated to the SO.
		:param grouped: if True, invoices are grouped by SO id. If False, invoices are grouped by
						(partner, currency)
		:param final: if True, refunds will be generated if necessary
		:returns: list of created invoices
		"""
        inv_obj = self.env['account.invoice']
        if self.type_order == 'claim':
            res = []
            for inv in self:
                inv_res = super(sale_order_entension,
                                inv).action_invoice_create(grouped=grouped,
                                                           final=final)
                result_obj = inv_obj.search([('id', 'in', inv_res)])
                for result in result_obj:
                    result.type_order = 'claim'
                    if result.company_id.id == 1:
                        result.carrier_id = inv.carrier_id.name
                        result.amount_freight = inv.delivery_price

            return res

        # if self.invoice_ids and self.import_text :
        # 	print "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        # 	for result in self.invoice_ids:
        # 		print "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
        # 		record.carrier_id = self.carrier_id.name or False
        # 		record.delivery_price = self.amount_freight

        if not split_invoice:
            res = []
            for order in self:
                order_res = super(sale_order_entension,
                                  order).action_invoice_create(grouped=grouped,
                                                               final=final)
                res.append(order_res)
                inv_rec = inv_obj.search([('id', 'in', order_res)])

                for invoice in inv_rec:
                    if order.import_text:
                        invoice.invoice_lines_boolean = order.import_text
                    if invoice.company_id.id == 1:
                        invoice.carrier_id = order.carrier_id.name
                        invoice.amount_freight = order.delivery_price

                    for box_line in order.product_packaging_one2many:
                        box_vals = {
                            'name': box_line.name.id,
                            'code': box_line.code,
                            'amount': box_line.amount,
                            'rate': box_line.rate,
                            'qty': box_line.qty,
                            'account_packaging_id': invoice.id
                        }
                        self.env['packaging.extension'].create(box_vals)

            return res
        else:

            precision = self.env['decimal.precision'].precision_get(
                'Product Unit of Measure')
            invoices = {}

            for order in self:
                comp_dict = {}

                for box_line in order.product_packaging_one2many:
                    c_id = box_line.name.company_id.id
                    if c_id in comp_dict:
                        comp_dict[c_id].append(box_line.code)
                    else:
                        comp_dict[c_id] = [box_line.code]

                for key, value in comp_dict.items():
                    invoice = False

                    group_key = str(order.id) + "," + str(key)

                    # for line in order.order_line.sorted(key=lambda l: l.qty_to_invoice < 0):
                    for line in order.order_line.sorted(
                            key=lambda l: l.product_id.product_packaging_id.
                            code):
                        if line.box_code.code in value:
                            if float_is_zero(line.qty_to_invoice,
                                             precision_digits=precision):
                                continue
                            if group_key not in invoices:
                                inv_data = order._prepare_invoice()
                                inv_data['company_id'] = key
                                inv_data[
                                    'invoice_lines_boolean'] = order.import_text
                                if key == 1:
                                    inv_data[
                                        'carrier_id'] = order.carrier_id.name
                                    inv_data[
                                        'amount_freight'] = order.delivery_price
                                invoice = inv_obj.create(inv_data)
                                invoices[group_key] = invoice
                            elif group_key in invoices and order.name not in invoices[
                                    group_key].origin.split(', '):
                                invoices[group_key].write({
                                    'origin':
                                    invoices[group_key].origin + ', ' +
                                    order.name
                                })
                            if line.qty_to_invoice > 0:

                                line.invoice_line_create(
                                    invoices[group_key].id,
                                    line.qty_to_invoice)
                            elif line.qty_to_invoice < 0 and final:
                                line.invoice_line_create(
                                    invoices[group_key].id,
                                    line.qty_to_invoice)

                    for box_line in order.product_packaging_one2many:
                        if box_line.code in value:
                            box_vals = {
                                'name': box_line.name.id,
                                'code': box_line.code,
                                'amount': box_line.amount,
                                'rate': box_line.rate,
                                'qty': box_line.qty,
                                'account_packaging_id': invoice.id
                            }
                            self.env['packaging.extension'].create(box_vals)

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

            return [inv.id for inv in invoices.values()]
    def do_merge(self,
                 keep_references=True,
                 date_invoice=False,
                 remove_empty_invoice_lines=True):
        """
        To merge similar type of account invoices.
        Invoices will only be merged if:
        * Account invoices are in draft
        * Account invoices belong to the same partner
        * Account invoices are have same company, partner, address, currency,
          journal, currency, salesman, account, type
        Lines will only be merged if:
        * Invoice lines are exactly the same except for the quantity and unit

         @param self: The object pointer.
         @param keep_references: If True, keep reference of original invoices

         @return: new account invoice id

        """
        def make_key(br, fields):
            list_key = []
            for field in fields:
                field_val = getattr(br, field)
                if field in ('product_id', 'account_id'):
                    if not field_val:
                        field_val = False
                if (isinstance(field_val, browse_record)
                        and field != 'invoice_line_tax_ids'
                        and field != 'sale_line_ids'):
                    field_val = field_val.id
                elif isinstance(field_val, browse_null):
                    field_val = False
                elif (isinstance(field_val, list)
                      or field == 'invoice_line_tax_ids'
                      or field == 'sale_line_ids'):
                    field_val = ((6, 0, tuple([v.id for v in field_val])), )
                list_key.append((field, field_val))
            list_key.sort()
            return tuple(list_key)

        # compute what the new invoices should contain

        new_invoices = {}
        draft_invoices = [
            invoice for invoice in self if invoice.state == 'draft'
        ]
        seen_origins = {}
        seen_client_refs = {}

        for account_invoice in draft_invoices:
            invoice_key = make_key(account_invoice,
                                   self._get_invoice_key_cols())
            new_invoice = new_invoices.setdefault(invoice_key, ({}, []))
            origins = seen_origins.setdefault(invoice_key, set())
            client_refs = seen_client_refs.setdefault(invoice_key, set())
            new_invoice[1].append(account_invoice.id)
            invoice_infos = new_invoice[0]
            if not invoice_infos:
                invoice_infos.update(
                    self._get_first_invoice_fields(account_invoice))
                origins.add(account_invoice.origin)
                client_refs.add(account_invoice.reference)
                if not keep_references:
                    invoice_infos.pop('name')
            else:
                if account_invoice.name and keep_references:
                    invoice_infos['name'] = \
                        (invoice_infos['name'] or '') + ' ' + \
                        account_invoice.name
                if account_invoice.origin and \
                        account_invoice.origin not in origins:
                    invoice_infos['origin'] = \
                        (invoice_infos['origin'] or '') + ' ' + \
                        account_invoice.origin
                    origins.add(account_invoice.origin)
                if account_invoice.reference \
                        and account_invoice.reference not in client_refs:
                    invoice_infos['reference'] = \
                        (invoice_infos['reference'] or '') + ' ' + \
                        account_invoice.reference
                    client_refs.add(account_invoice.reference)

            for invoice_line in account_invoice.invoice_line_ids:
                line_key = make_key(invoice_line,
                                    self._get_invoice_line_key_cols())

                o_line = invoice_infos['invoice_line_ids'].\
                    setdefault(line_key, {})

                if o_line:
                    # merge the line with an existing line
                    o_line['quantity'] += invoice_line.quantity
                else:
                    # append a new "standalone" line
                    o_line['quantity'] = invoice_line.quantity

        allinvoices = []
        allnewinvoices = []
        invoices_info = {}
        qty_prec = self.env['decimal.precision'].precision_get(
            'Product Unit of Measure')
        for invoice_key, (invoice_data, old_ids) in new_invoices.iteritems():
            # skip merges with only one invoice
            if len(old_ids) < 2:
                allinvoices += (old_ids or [])
                continue
            # cleanup invoice line data
            for key, value in invoice_data['invoice_line_ids'].iteritems():
                value.update(dict(key))

            if remove_empty_invoice_lines:
                invoice_data['invoice_line_ids'] = [
                    (0, 0, value)
                    for value in invoice_data['invoice_line_ids'].itervalues()
                    if not float_is_zero(value['quantity'],
                                         precision_digits=qty_prec)
                ]
            else:
                invoice_data['invoice_line_ids'] = [
                    (0, 0, value)
                    for value in invoice_data['invoice_line_ids'].itervalues()
                ]

            if date_invoice:
                invoice_data['date_invoice'] = date_invoice

            # create the new invoice
            newinvoice = self.with_context(is_merge=True).create(invoice_data)
            invoices_info.update({newinvoice.id: old_ids})
            allinvoices.append(newinvoice.id)
            allnewinvoices.append(newinvoice)
            # make triggers pointing to the old invoices point to the new
            # invoice
            for old_id in old_ids:
                workflow.trg_redirect(self.env.uid, 'account.invoice', old_id,
                                      newinvoice.id, self.env.cr)
                workflow.trg_validate(self.env.uid, 'account.invoice', old_id,
                                      'invoice_cancel', self.env.cr)

        # Make link between original sale order
        # None if sale is not installed
        so_obj = self.env['sale.order'] \
            if 'sale.order' in self.env.registry else False
        invoice_line_obj = self.env['account.invoice.line']
        for new_invoice_id in invoices_info:
            if so_obj is not False:
                todos = so_obj.search([('invoice_ids', 'in',
                                        invoices_info[new_invoice_id])])
                todos.write({'invoice_ids': [(4, new_invoice_id)]})
                for org_so in todos:
                    for so_line in org_so.order_line:
                        invoice_lines = invoice_line_obj.search([
                            ('product_id', '=', so_line.product_id.id),
                            ('invoice_id', '=', new_invoice_id)
                        ])
                        if invoice_lines:
                            so_line.write(
                                {'invoice_lines': [(6, 0, invoice_lines.ids)]})

        # recreate link (if any) between original analytic account line
        # (invoice time sheet for example) and this new invoice
        anal_line_obj = self.env['account.analytic.line']
        if 'invoice_id' in anal_line_obj._columns:
            for new_invoice_id in invoices_info:
                todos = anal_line_obj.search([('invoice_id', 'in',
                                               invoices_info[new_invoice_id])])
                todos.write({'invoice_id': new_invoice_id})

        for new_invoice in allnewinvoices:
            new_invoice.compute_taxes()

        return invoices_info
Exemple #53
0
    def _add_invoice_line_block(self, trade_transaction, iline, line_number,
                                sign, ns):
        self.ensure_one()
        dpo = self.env['decimal.precision']
        pp_prec = dpo.precision_get('Product Price')
        disc_prec = dpo.precision_get('Discount')
        qty_prec = dpo.precision_get('Product Unit of Measure')
        inv_currency_name = self.currency_id.name
        line_item = etree.SubElement(
            trade_transaction, ns['ram'] + 'IncludedSupplyChainTradeLineItem')
        line_doc = etree.SubElement(
            line_item, ns['ram'] + 'AssociatedDocumentLineDocument')
        etree.SubElement(line_doc,
                         ns['ram'] + 'LineID').text = unicode(line_number)
        line_trade_agreement = etree.SubElement(
            line_item, ns['ram'] + 'SpecifiedSupplyChainTradeAgreement')
        # convert gross price_unit to tax_excluded value
        taxres = iline.invoice_line_tax_id.compute_all(iline.price_unit, 1)
        gross_price_val = float_round(taxres['total'],
                                      precision_digits=pp_prec)
        # Use oline.price_subtotal/qty to compute net unit price to be sure
        # to get a *tax_excluded* net unit price
        if float_is_zero(iline.quantity, precision_digits=qty_prec):
            net_price_val = 0.0
        else:
            net_price_val = float_round(iline.price_subtotal /
                                        float(iline.quantity),
                                        precision_digits=pp_prec)
        gross_price = etree.SubElement(
            line_trade_agreement, ns['ram'] + 'GrossPriceProductTradePrice')
        gross_price_amount = etree.SubElement(gross_price,
                                              ns['ram'] + 'ChargeAmount',
                                              currencyID=inv_currency_name)
        gross_price_amount.text = unicode(gross_price_val)
        fc_discount = float_compare(iline.discount,
                                    0.0,
                                    precision_digits=disc_prec)
        if fc_discount in [-1, 1]:
            trade_allowance = etree.SubElement(
                gross_price, ns['ram'] + 'AppliedTradeAllowanceCharge')
            charge_indic = etree.SubElement(trade_allowance,
                                            ns['ram'] + 'ChargeIndicator')
            indicator = etree.SubElement(charge_indic, ns['udt'] + 'Indicator')
            if fc_discount == 1:
                indicator.text = 'false'
            else:
                indicator.text = 'true'
            actual_amount = etree.SubElement(trade_allowance,
                                             ns['ram'] + 'ActualAmount',
                                             currencyID=inv_currency_name)
            actual_amount_val = float_round(gross_price_val - net_price_val,
                                            precision_digits=pp_prec)
            actual_amount.text = unicode(abs(actual_amount_val))

        net_price = etree.SubElement(line_trade_agreement,
                                     ns['ram'] + 'NetPriceProductTradePrice')
        net_price_amount = etree.SubElement(net_price,
                                            ns['ram'] + 'ChargeAmount',
                                            currencyID=inv_currency_name)
        net_price_amount.text = unicode(net_price_val)
        line_trade_delivery = etree.SubElement(
            line_item, ns['ram'] + 'SpecifiedSupplyChainTradeDelivery')
        if iline.uos_id and iline.uos_id.unece_code:
            unitCode = iline.uos_id.unece_code
        else:
            unitCode = 'C62'
            if not iline.uos_id:
                logger.warning(
                    "No unit of measure on invoice line '%s', "
                    "using C62 (piece) as fallback", iline.name)
            else:
                logger.warning(
                    'Missing UNECE Code on unit of measure %s, '
                    'using C62 (piece) as fallback', iline.uos_id.name)
        billed_qty = etree.SubElement(line_trade_delivery,
                                      ns['ram'] + 'BilledQuantity',
                                      unitCode=unitCode)
        billed_qty.text = unicode(iline.quantity * sign)
        line_trade_settlement = etree.SubElement(
            line_item, ns['ram'] + 'SpecifiedSupplyChainTradeSettlement')
        if iline.invoice_line_tax_id:
            for tax in iline.invoice_line_tax_id:
                trade_tax = etree.SubElement(line_trade_settlement,
                                             ns['ram'] + 'ApplicableTradeTax')
                trade_tax_typecode = etree.SubElement(trade_tax,
                                                      ns['ram'] + 'TypeCode')
                if not tax.unece_type_code:
                    raise UserError(
                        _("Missing UNECE Tax Type on tax '%s'") % tax.name)
                trade_tax_typecode.text = tax.unece_type_code
                trade_tax_categcode = etree.SubElement(
                    trade_tax, ns['ram'] + 'CategoryCode')
                if not tax.unece_categ_code:
                    raise UserError(
                        _("Missing UNECE Tax Category on tax '%s'") % tax.name)
                trade_tax_categcode.text = tax.unece_categ_code
                if tax.type == 'percent':
                    trade_tax_percent = etree.SubElement(
                        trade_tax, ns['ram'] + 'ApplicablePercent')
                    trade_tax_percent.text = unicode(tax.amount * 100)
        subtotal = etree.SubElement(
            line_trade_settlement,
            ns['ram'] + 'SpecifiedTradeSettlementMonetarySummation')
        subtotal_amount = etree.SubElement(subtotal,
                                           ns['ram'] + 'LineTotalAmount',
                                           currencyID=inv_currency_name)
        subtotal_amount.text = unicode(iline.price_subtotal * sign)
        trade_product = etree.SubElement(line_item,
                                         ns['ram'] + 'SpecifiedTradeProduct')
        if iline.product_id:
            if iline.product_id.ean13:
                ean13 = etree.SubElement(trade_product,
                                         ns['ram'] + 'GlobalID',
                                         schemeID='0160')
                # 0160 = GS1 Global Trade Item Number (GTIN, EAN)
                ean13.text = iline.product_id.ean13
            if iline.product_id.default_code:
                product_code = etree.SubElement(trade_product,
                                                ns['ram'] + 'SellerAssignedID')
                product_code.text = iline.product_id.default_code
        product_name = etree.SubElement(trade_product, ns['ram'] + 'Name')
        product_name.text = iline.name
        if iline.product_id and iline.product_id.description_sale:
            product_desc = etree.SubElement(trade_product,
                                            ns['ram'] + 'Description')
            product_desc.text = iline.product_id.description_sale
 def _is_difference_zero(self):
     for bank_stmt in self:
         bank_stmt.is_difference_zero = float_is_zero(bank_stmt.difference, precision_digits=bank_stmt.currency_id.decimal_places)
Exemple #55
0
    def bouton_confirm(self):
        #preparing invoice

        for actesmedicaux in self:

            if not actesmedicaux.actesmedicaux_lines:
                raise UserError(_('There is no medical acts line.'))
            if actesmedicaux.actesmedicaux_lines:
                self.ensure_one()
                journal_id = self.env['account.invoice'].default_get(
                    ['journal_id'])['journal_id']
                if not journal_id:
                    raise osv.except_osv(
                        _('Attention!!'),
                        _('Please define an accounting sale journal for this company.'
                          ))

                invoice_vals = {
                    'name':
                    actesmedicaux.patient_id.partner_id.name,
                    'actesmedicaux_id':
                    actesmedicaux.id,
                    'physician_id':
                    actesmedicaux.physician_id.id,
                    'origin':
                    'Hospitalization -> #%s' % (actesmedicaux.id),
                    'type':
                    'out_invoice',
                    'account_id':
                    actesmedicaux.patient_id.partner_id.
                    property_account_receivable_id.id,
                    'partner_id':
                    actesmedicaux.patient_id.partner_id.id,
                    'journal_id':
                    journal_id,
                    'currency_id':
                    actesmedicaux.product_id.currency_id.id,
                    'comment':
                    '------------- ',
                    'payment_term_id':
                    actesmedicaux.patient_id.partner_id.
                    property_payment_term_id.id,
                    'fiscal_position_id':
                    actesmedicaux.patient_id.partner_id.
                    property_account_position_id.id,
                    'company_id':
                    actesmedicaux.patient_id.partner_id.company_id.id,
                    'user_id':
                    actesmedicaux.create_uid.id,
                    'team_id':
                    actesmedicaux.create_uid.team_id.id
                }

                invoice = self.env['account.invoice'].create(invoice_vals)

                for line in actesmedicaux.actesmedicaux_lines:
                    if not line.product_id.property_account_income_id and not line.product_id.categ_id.property_account_income_categ_id:
                        raise osv.except_osv(
                            _('Attention!!'),
                            _('Please specify the revenue account in the accounting tab of this Medical act or product(service).'
                              ))
                    #actesmedicaux.write({'end_date':fields.Date.context_today(self)})

                    #raise osv.except_osv(_('INVOICE %s' % (invoice.id)),_(' Is it the true?.'))
                    #invoice= self.env['account.invoice'].browse(invoice.id)
                    precision = self.env['decimal.precision'].precision_get(
                        'Product Unit of Measure')
                    if float_is_zero(line.product_uom_qty,
                                     precision_digits=precision):
                        continue
                    property_account_income_id = False
                    if line.product_id.property_account_income_id:
                        property_account_income_id = line.product_id.property_account_income_id.id
                    else:
                        property_account_income_id = line.product_id.categ_id.property_account_income_categ_id.id

                    invoice_line_vals = {
                        'name':
                        line.product_id.name,
                        'origin':
                        'INV: %s => %s' %
                        (invoice.id, actesmedicaux.patient_id.partner_id.name),
                        'sequence':
                        1,
                        'invoice_id':
                        invoice.id,
                        'uom_id':
                        line.product_id.uom_id.id,
                        'product_id':
                        line.product_id.id,
                        'account_id':
                        property_account_income_id,
                        'price_unit':
                        line.
                        price_unit,  #Envisager d'appeler plutot la fonction qui renvoie le prix de la liste des prix (self.lit_id.categorie_id.product_id.list_price,) 
                        'price_subtotal':
                        line.price_subtotal,
                        'price_subtotal_signed':
                        line.price_subtotal,
                        'quantity':
                        line.product_uom_qty,
                        'discount':
                        0,
                        'company_id':
                        actesmedicaux.patient_id.partner_id.company_id.id,
                        'partner_id':
                        actesmedicaux.patient_id.partner_id.id,
                        'currency_id':
                        line.product_id.currency_id.id,
                        'company_currency_id':
                        line.product_id.currency_id.id,
                        #'invoice_line_tax_ids':
                        'account_analytic_id':
                        False
                    }
                    invoice_line = self.env['account.invoice.line'].create(
                        invoice_line_vals)
                    #raise osv.except_osv(_('INVOICE %s' % (invoice.id)),_(' Is it the true?.'))
                    #invoice_line= self.env['account.invoice.line'].browse(ids_invoice_line[0])
                    invoice_line._set_taxes()
                    invoice_line._compute_price()
                    self.env['account.invoice.line'].write(invoice_line)

                invoice._onchange_invoice_line_ids()
                invoice._compute_amount()
                vals = {
                    'tax_line_ids': invoice.tax_line_ids,
                    'amount_untaxed': invoice.amount_untaxed,
                    'amount_tax': invoice.amount_tax,
                    'amount_total': invoice.amount_total,
                    'amount_total_company_signed':
                    invoice.amount_total_company_signed,
                    'amount_total_signed': invoice.amount_total_signed,
                    'amount_untaxed_signed': invoice.amount_untaxed_signed,
                }
                invoice.write(vals)

                #invoice.invoice_validate()(
                #invoice.write(invoice)
                #invoice.post()
                #invoice_line.post()

                #raise osv.except_osv(_('INVOICE %s' % (invoice.id)),_(' Is it the true....?.'))

                actesmedicaux.write({
                    'state': 'confirm',
                    'invoice_id': invoice.id
                })
                #update = "update hospital_actesmedicaux set state = '%s',invoice_id = %s where id = %s" % ('confirm',invoice.id, actesmedicaux.id)
                #self.env.cr.execute(str(update))
                #try:
                #except ValueError:
                #    print("Error Value.")
                #except indexError:
                #    print("Erorr index")
                #except :
                #    print('error ')

                # La part des practiciens extérieurs
                # envisager aussi de calculer la part losque le praticien est employé

                if not actesmedicaux.physician_id.employee_id:
                    # Le practicien est quelcun de l'exterieur. Si la règle est défini alors on génere la facture d'achat de service pour ce dernier

                    #actesmedicaux.write({'end_date':fields.Date.context_today(self)})

                    invoice_vals = {
                        'name':
                        actesmedicaux.physician_id.partner_id.name,
                        'actesmedicaux_id':
                        actesmedicaux.id,
                        'physician_id':
                        actesmedicaux.physician_id.id,
                        'origin':
                        'Medical Act -> #%s' % (actesmedicaux.id),
                        'type':
                        'in_invoice',
                        'account_id':
                        actesmedicaux.physician_id.partner_id.
                        property_account_payable_id.id,
                        'partner_id':
                        actesmedicaux.physician_id.partner_id.id,
                        'journal_id':
                        journal_id,
                        'currency_id':
                        actesmedicaux.product_id.currency_id.id,
                        'comment':
                        '------------- ',
                        'payment_term_id':
                        actesmedicaux.physician_id.partner_id.
                        property_supplier_payment_term_id.id,
                        'fiscal_position_id':
                        actesmedicaux.physician_id.partner_id.
                        property_account_position_id.id,
                        'company_id':
                        actesmedicaux.physician_id.partner_id.company_id.id,
                        'user_id':
                        actesmedicaux.create_uid.id,
                        'team_id':
                        actesmedicaux.create_uid.team_id.id
                    }

                    invoice = self.env['account.invoice'].create(invoice_vals)

                    for line in actesmedicaux.actesmedicaux_lines:
                        if not line.product_id.property_account_expense_id and not line.product_id.categ_id.property_account_expense_categ_id:
                            raise osv.except_osv(
                                _('Attention!!'),
                                _('Please specify the expense account in the accounting tab of this Medical act or product(service).'
                                  ))
                        #raise osv.except_osv(_('INVOICE %s' % (invoice.id)),_(' Is it the true?.'))
                        #invoice= self.env['account.invoice'].browse(invoice.id)
                        precision = self.env[
                            'decimal.precision'].precision_get(
                                'Product Unit of Measure')
                        if float_is_zero(
                                line.product_uom_qty,
                                precision_digits=precision
                        ) or line.product_id.product_tmpl_id.type != 'service':
                            continue

                        percent_phisician = 100
                        recs = self.env['physician.payment.term'].search([
                            '&', ('product_id', '=', line.product_id.id),
                            ('physician_id', '=',
                             actesmedicaux.physician_id.id),
                            ('state', '=', 'activate')
                        ])
                        if not recs:
                            recs = self.env['physician.payment.term'].search([
                                '&', ('product_id', '=', line.product_id.id),
                                ('state', '=', 'activate')
                            ])
                            if not recs:
                                recs = self.env[
                                    'physician.payment.term'].search([
                                        '&',
                                        ('physician_id', '=',
                                         actesmedicaux.physician_id.id),
                                        ('state', '=', 'activate')
                                    ])
                                if recs:
                                    continue
                                else:
                                    raise osv.except_osv(
                                        _('Configuration!!'),
                                        _('Please, for the service product %s specify the physician payment term if the physician is an external consultant or his employee id if he is an employee'
                                          % (line.product_id.name)))

                        if recs:
                            for term in recs:
                                percent_phisician = term.percent_phisician

                        property_account_expense_id = False
                        if line.product_id.property_account_income_id:
                            property_account_expense_id = line.product_id.property_account_expense_id.id
                        else:
                            property_account_expense_id = line.product_id.categ_id.property_account_expense_categ_id.id

                        invoice_line_vals = {
                            'name':
                            line.product_id.name,
                            'origin':
                            'INV: %s => %s' %
                            (invoice.id,
                             actesmedicaux.patient_id.partner_id.name),
                            'sequence':
                            1,
                            'invoice_id':
                            invoice.id,
                            'uom_id':
                            line.product_id.uom_id.id,
                            'product_id':
                            line.product_id.id,
                            'account_id':
                            property_account_expense_id,
                            'price_unit':
                            line.price_unit * (
                                percent_phisician / 100
                            ),  #Envisager d'appeler plutot la fonction qui renvoie le prix de la liste des prix (self.lit_id.categorie_id.product_id.list_price,) 
                            'price_subtotal':
                            line.product_uom_qty * line.price_unit *
                            (percent_phisician / 100),
                            'price_subtotal_signed':
                            line.product_uom_qty * line.price_unit *
                            (percent_phisician / 100),
                            'quantity':
                            line.product_uom_qty,
                            'discount':
                            0,
                            'company_id':
                            actesmedicaux.physician_id.partner_id.company_id.
                            id,
                            'partner_id':
                            actesmedicaux.physician_id.partner_id.id,
                            'currency_id':
                            line.product_id.currency_id.id,
                            'company_currency_id':
                            line.product_id.currency_id.id,
                            #'invoice_line_tax_ids':
                            'account_analytic_id':
                            False
                        }
                        invoice_line = self.env['account.invoice.line'].create(
                            invoice_line_vals)
                        #raise osv.except_osv(_('INVOICE %s' % (invoice.id)),_(' Is it the true?.'))
                        #invoice_line= self.env['account.invoice.line'].browse(ids_invoice_line[0])
                        invoice_line._set_taxes()
                        invoice_line._compute_price()
                        self.env['account.invoice.line'].write(invoice_line)

                    invoice._onchange_invoice_line_ids()
                    invoice._compute_amount()
                    vals = {
                        'tax_line_ids': invoice.tax_line_ids,
                        'amount_untaxed': invoice.amount_untaxed,
                        'amount_tax': invoice.amount_tax,
                        'amount_total': invoice.amount_total,
                        'amount_total_company_signed':
                        invoice.amount_total_company_signed,
                        'amount_total_signed': invoice.amount_total_signed,
                        'amount_untaxed_signed': invoice.amount_untaxed_signed,
                    }
                    invoice.write(vals)
                    actesmedicaux.write({'supplier_invoice_id': invoice.id})
Exemple #56
0
    def validate(self):
        check_total = self.env['res.users'].has_group(
            'donation.group_donation_check_total')
        precision = self.env['decimal.precision'].precision_get('Account')
        for donation in self:
            if not donation.line_ids:
                raise UserError(
                    _("Cannot validate the donation of %s because it doesn't "
                      "have any lines!") % donation.partner_id.name)

            if float_is_zero(donation.amount_total,
                             precision_digits=precision):
                raise UserError(
                    _("Cannot validate the donation of %s because the "
                      "total amount is 0 !") % donation.partner_id.name)

            if donation.state != 'transfer':
                raise UserError(
                    _("Cannot validate the donation of %s because it is not "
                      "in transfer state.") % donation.partner_id.name)

            if check_total and donation.check_total != donation.amount_total:
                raise UserError(
                    _("The amount of the donation of %s (%s) is different "
                      "from the sum of the donation lines (%s).") %
                    (donation.partner_id.name, donation.check_total,
                     donation.amount_total))
            vals = {'state': 'done'}
            if donation.amount_total:
                move_vals = donation._prepare_donation_move()
                move_analytic_vals = donation._prepare_analytic_line()[0]
                # when we have a full in-kind donation: no account move
                if move_vals:
                    move = self.env['account.move'].create(move_vals)
                    #move.post()
                    move_id2 = move.id
                    vals['move_id'] = move.id
                    move_analytic = self.env['account.analytic.line'].create(
                        move_analytic_vals)
                    move_analytic2 = move_analytic.id
                    analytic = self.campaign_id.analytic_account_id.id
                    vals['move_analytic_id'] = move_analytic.id
                    self.env.cr.execute(
                        "SELECT id FROM account_move_line where move_id = '%s' and analytic_account_id ='%d'"
                        % (move.id, analytic))
                    res111 = self.env.cr.fetchone()[0]
                    #ress = (move.id*2) - 1
                    self.env.cr.execute(
                        "UPDATE account_analytic_line set move_id= '%s' where id= '%d'"
                        % (res111, move_analytic.id))

                    resss = self.account_id.id
                    self.env.cr.execute(
                        "UPDATE account_analytic_line set general_account_id= '%s' where id= '%d'"
                        % (resss, move_analytic.id))

                    ressss = self.commercial_partner_id.id
                    self.env.cr.execute(
                        "UPDATE account_analytic_line set partner_id= '%s' where id= '%d'"
                        % (ressss, move_analytic.id))

                    ress2 = move_analytic.id
                    self.env.cr.execute(
                        "SELECT place.tag_id FROM donation_donation inner join donation_place as place on donation_donation.donation_place = place.id where donation_donation.id= '%s'"
                        % (self.id))
                    res11 = self.env.cr.fetchone()[0]
                    self.env.cr.execute(
                        "insert INTO account_analytic_line_tag_rel(line_id, tag_id) VALUES ('%s','%s')"
                        % (ress2, res11))

                    self.env.cr.execute(
                        "SELECT gov.tag_id FROM donation_donation inner join govs_villages_gov as gov on donation_donation.gov_id = gov.id where donation_donation.id= '%s'"
                        % (self.id))
                    res12 = self.env.cr.fetchone()[0]
                    self.env.cr.execute(
                        "insert INTO account_analytic_line_tag_rel(line_id, tag_id) VALUES ('%s','%s')"
                        % (ress2, res12))

                    self.env.cr.execute(
                        "SELECT method.tag_id FROM donation_donation inner join donation_instrument as method on donation_donation.donation_method = method.id where donation_donation.id= '%s'"
                        % (self.id))
                    res13 = self.env.cr.fetchone()[0]
                    self.env.cr.execute(
                        "insert INTO account_analytic_line_tag_rel(line_id, tag_id) VALUES ('%s','%s')"
                        % (ress2, res13))
                else:
                    donation.message_post(
                        _('Full in-kind donation: no account move generated'))
            if (donation.tax_receipt_option == 'each'
                    and donation.tax_receipt_total
                    and not donation.tax_receipt_id):
                receipt_vals = donation._prepare_each_tax_receipt()
                receipt = self.env['donation.tax.receipt'].create(receipt_vals)
                vals['tax_receipt_id'] = receipt.id
            donation.write(vals)
        return
Exemple #57
0
    def action_produce(self, cr, uid, production_id, production_qty, production_mode, wiz=False, context=None):
        """ Aplicado a usar precio promedio ponderado considerando
        1.- Producción total.- se consumo y se da de alta lo que se planifica
        2.- Producción parcial.- Cada consumo parcial genera diferente costo
        3.- Exceso de consumo de insumos
        4.- Exceso de producción de producto final
        """
        stock_mov_obj = self.pool.get('stock.move')
        uom_obj = self.pool.get("product.uom")
        production = self.browse(cr, uid, production_id, context=context)
        production_qty_uom = uom_obj._compute_qty(cr, uid, production.product_uom.id, production_qty, production.product_id.uom_id.id)
        precision = self.pool['decimal.precision'].precision_get(cr, uid, 'Product Unit of Measure')

        main_production_move = False
        if production_mode == 'consume_produce':
            for produce_product in production.move_created_ids:
                if produce_product.product_id.id == production.product_id.id:
                    main_production_move = produce_product.id

        total_consume_moves = set()
        if production_mode in ['consume', 'consume_produce']:
            if wiz:
                consume_lines = []
                for cons in wiz.consume_lines:
                    consume_lines.append({'product_id': cons.product_id.id, 'lot_id': cons.lot_id.id, 'product_qty': cons.product_qty})
            else:
                consume_lines = self._calculate_qty(cr, uid, production, production_qty_uom, context=context)
            for consume in consume_lines:
                remaining_qty = consume['product_qty']
                for raw_material_line in production.move_lines:
                    if raw_material_line.state in ('done', 'cancel'):
                        continue
                    if remaining_qty <= 0:
                        break
                    if consume['product_id'] != raw_material_line.product_id.id:
                        continue
                    consumed_qty = min(remaining_qty, raw_material_line.product_qty)
                    stock_mov_obj.action_consume(cr, uid, [raw_material_line.id], consumed_qty, raw_material_line.location_id.id,
                                                 restrict_lot_id=consume['lot_id'], consumed_for=main_production_move, context=context)
                    total_consume_moves.add(raw_material_line.id)
                    remaining_qty -= consumed_qty
                if not float_is_zero(remaining_qty, precision_digits=precision):
                    #consumed more in wizard than previously planned
                    product = self.pool.get('product.product').browse(cr, uid, consume['product_id'], context=context)
                    extra_move_id = self._make_consume_line_from_data(cr, uid, production, product, product.uom_id.id, remaining_qty, context=context)
                    stock_mov_obj.write(cr, uid, [extra_move_id], {'restrict_lot_id': consume['lot_id'],
                                                                    'consumed_for': main_production_move}, context=context)
                    stock_mov_obj.action_done(cr, uid, [extra_move_id], context=context)
                    total_consume_moves.add(extra_move_id)

        if production_mode == 'consume_produce':
            # add production lines that have already been consumed since the last 'consume & produce'
            last_production_date = production.move_created_ids2 and max(production.move_created_ids2.mapped('date')) or False
            already_consumed_lines = production.move_lines2.filtered(lambda l: l.date > last_production_date)
            total_consume_moves = total_consume_moves.union(already_consumed_lines.ids)

            price_unit = 0
            for produce_product in production.move_created_ids:
                is_main_product = (produce_product.product_id.id == production.product_id.id) and production.product_id.cost_method=='real'
                #if is_main_product:
                if production.product_id.cost_method in ('real', 'average'):
                    total_cost = self._calculate_total_cost(cr, uid, list(total_consume_moves), context=context)
                    production_cost = self._calculate_workcenter_cost(cr, uid, production_id, context=context)
                    price_unit = (total_cost + production_cost) / production_qty_uom

                subproduct_factor = self._get_subproduct_factor(cr, uid, production.id, produce_product.id, context=context)
                lot_id = False
                if wiz:
                    lot_id = wiz.lot_id.id
                qty = min(subproduct_factor * production_qty_uom, produce_product.product_qty) #Needed when producing more than maximum quantity
                #if is_main_product and price_unit:
                if production.product_id.cost_method in ('real', 'average'):
                    stock_mov_obj.write(cr, uid, [produce_product.id], {'price_unit': price_unit}, context=context)
                new_moves = stock_mov_obj.action_consume(cr, uid, [produce_product.id], qty,
                                                         location_id=produce_product.location_id.id, restrict_lot_id=lot_id, context=context)
                stock_mov_obj.write(cr, uid, new_moves, {'production_id': production_id}, context=context)
                remaining_qty = subproduct_factor * production_qty_uom - qty
                if not float_is_zero(remaining_qty, precision_digits=precision):
                    # In case you need to make more than planned
                    #consumed more in wizard than previously planned
                    extra_move_id = stock_mov_obj.copy(cr, uid, produce_product.id, default={'product_uom_qty': remaining_qty,
                                                                                             'production_id': production_id}, context=context)
                    if is_main_product:
                        stock_mov_obj.write(cr, uid, [extra_move_id], {'price_unit': price_unit}, context=context)
                    stock_mov_obj.action_confirm(cr, uid, [extra_move_id], context=context)
                    stock_mov_obj.action_done(cr, uid, [extra_move_id], context=context)

        self.message_post(cr, uid, production_id, body=_("%s produced") % self._description, context=context)

        # Remove remaining products to consume if no more products to produce
        if not production.move_created_ids and production.move_lines:
            stock_mov_obj.action_cancel(cr, uid, [x.id for x in production.move_lines], context=context)

        self.signal_workflow(cr, uid, [production_id], 'button_produce_done')
        return True