Beispiel #1
0
 def sale_lines(self, record):
     product_obj = self.session.pool.get('product.product')
     pricelist_obj = self.session.pool.get('product.pricelist')
     order_lines = []
     for sale_line in record['line']:
         # TODO: Can handle UoM with sale_line['ordunit'] if they vary from single units
         pricelist_id = self.backend_record.shop_id.pricelist_id.id
         product_binder = self.get_binder_for_model('bots.product')
         product_id = product_binder.to_openerp(sale_line['product_sku'])
         if not product_id:
             raise NoExternalId("Product %s could not be found in OpenERP" % (sale_line['product_sku'],))
         product = product_obj.browse(self.session.cr, self.session.uid, product_id)
         product_qty = int(sale_line['qty'])
         if not self.backend_record.catalog_price_tax_included:
             list_values = pricelist_obj.price_get(self.session.cr, self.session.uid, [pricelist_id], product_id, product_qty)
             list_price = list_values[pricelist_id]
             if list_price:
                 # FIXME: Due to the precision of the discount we need to reverse engineer the list price in the SO
                 # line so we get the correct total price while keeping the list price as close as possible to the origional
                 discount_dp = dp.get_precision('Discount')(self.session.cr)[1]
                 discount = round((1 - float(sale_line['price'])/list_price) * 100.0, discount_dp)
                 list_price = float(sale_line['price']) / (1.0 - (discount / 100.0))
             else:
                 list_price = float(sale_line['price'])
                 discount = 0
         else:
             raise NotImplementedError('Only tax exclusive prices are implimented currently, disable "Prices include tax" in the backend')
         order_line = [0, 0, {'name': product.name,
                              'product_id': product_id,
                              'product_uom_qty': product_qty,
                              'price_unit': list_price,
                              'discount': discount,
                              }]
         order_lines.append(order_line)
     return {'order_line': order_lines}
 def balance_move(self, cr, uid, move_id, context=None):
     currency_obj = self.pool.get('res.currency')
     move = self.pool.get('account.move').browse(cr, uid, move_id, context)
     amount = 0.0
     for line in move.line_id:
         amount += line.debit - line.credit
     amount = currency_obj.round(cr, uid, move.company_id.currency_id, amount)
     # check if balance differs for more than 1 decimal according to account decimal precision
     if  abs(amount * 10 ** dp.get_precision('Account')(cr)[1]) > 1:
         raise osv.except_osv(_('Error'), _('The generated payment entry is unbalanced for more than 1 decimal'))
     if not currency_obj.is_zero(cr, uid, move.company_id.currency_id, amount):
         for line in move.line_id:
             # adjust the first move line that's not receivable, payable or liquidity
             if line.account_id.type != 'receivable' and line.account_id.type != 'payable' and line.account_id.type != 'liquidity':
                 if line.credit:
                     line.write({
                         'credit': line.credit + amount,
                         }, update_check=False)
                 elif line.debit:
                     line.write({
                         'debit': line.debit - amount,
                         }, update_check=False)
                 if line.tax_amount:
                     line.write({
                         'tax_amount': line.tax_amount + amount,
                         }, update_check=False)
                 break
     return amount
Beispiel #3
0
 def simplified_limit_check(self):
     for order in self:
         if not order.simplified:
             continue
         limit = order.session_id.config_id.simplified_invoice_limit
         amount_total = order.amount_total
         precision_digits = dp.get_precision('Account')(self.env.cr)[1]
         # -1 or 0: amount_total <= limit, simplified
         #       1: amount_total > limit, can not be simplified
         simplified = (
             float_compare(amount_total, limit,
                           precision_digits=precision_digits) <= 0)
         # Change simplified flag if incompatible
         if not simplified:
             order.write({'simplified': simplified})
Beispiel #4
0
	def _qty_all_2(self, cr, uid, ids, field_name, arg, context=None):
		result = {} 
	
		for line in self.browse(cr, uid, ids, context=context):
			qty = line.qty2_2
			uom = line.uom_id.factor_inv
			qty_all = round(qty*uom,3)
			result[line.id] = qty_all
		return result

	_columns = {
		'name' : fields.char('Name', required=True),
		'partner_id' : fields.many2one('res.partner','Principle',domain=[('supplier','=',True)],required=True),
		'product_id' : fields.many2one('product.product','Bonus Product'),
		'qty_2' : fields.float('Bonus Qty2', digits_compute=dp.get_precision('Product Unit of Measure')),
		'qty' : fields.function(_qty_all_1,type="float",string='Bonus Qty',digits_compute=dp.get_precision('Product Unit of Measure')),
		'uom_id' : fields.many2one('product.uom','UoM',required=True),
		'uom_id2' : fields.many2one('product.uom','UoM',required=True),
		'value' : fields.float('Price Value',domain=[('is_percent','=',False)]),
		'per_product' : fields.boolean('Per Product'),
		'persentase' : fields.float('Percent Value', digits_compute= dp.get_precision('Discount'),domain=[('is_percent','=',True)]),
		'multi' : fields.boolean('Multiples'),
		'is_active' : fields.boolean('Active?'),
		'date_from' : fields.date('Start Date', required=True),
		'date_to' : fields.date('End Date', required=True),
		'condition_ids' : fields.one2many('master.condition','discount_id','Value Condition'),
		'condition2_ids' : fields.one2many('master.condition2','discount_id','Product Condition'),
		'condition3_ids' : fields.one2many('master.condition3','discount_id','Product Condition 2'),
		'condition4_ids' : fields.one2many('master.condition4','discount_id','Product Condition 3'),
		'condition5_ids' : fields.one2many('master.condition5','discount_id','Product Condition 4'),
class proforma_invoice_line(osv.osv):
    def _amount_line(self, cr, uid, ids, prop, unknow_none, unknow_dict):
        res = {}
        tax_obj = self.pool.get('account.tax')
        cur_obj = self.pool.get('res.currency')
        for line in self.browse(cr, uid, ids):
            price = line.price_unit
            taxes = tax_obj.compute_all(cr,
                                        uid,
                                        line.invoice_line_tax_id,
                                        price,
                                        line.quantity,
                                        product=line.product_id,
                                        partner=line.invoice_id.partner_id)
            res[line.id] = taxes['total']
            if line.invoice_id:
                cur = line.invoice_id.currency_id
                res[line.id] = cur_obj.round(cr, uid, cur, res[line.id])
        return res

    _name = "proforma.invoice.line"
    _description = "Proforma Invoice Line"
    _order = "invoice_id,sequence,id"
    _columns = {
        'name':
        fields.text('Description', required=True),
        'origin':
        fields.char(
            'Source Document',
            size=256,
            help=
            "Reference of the document that produced this proforma invoice."),
        'sequence':
        fields.integer(
            'Sequence',
            help="Gives the sequence of this line when displaying the invoice."
        ),
        'invoice_id':
        fields.many2one('proforma.invoice',
                        'Proforma Invoice',
                        ondelete='cascade',
                        select=True),
        'uom_id':
        fields.many2one('product.uom',
                        'Unit of Measure',
                        ondelete='set null',
                        select=True),
        'product_id':
        fields.many2one('product.product',
                        'Product',
                        ondelete='set null',
                        select=True),
        'price_unit':
        fields.float('Unit Price',
                     required=True,
                     digits_compute=dp.get_precision('Product Price')),
        'price_subtotal':
        fields.function(_amount_line,
                        string='Amount',
                        type="float",
                        digits_compute=dp.get_precision('Account')),
        'invoice_line_tax_id':
        fields.many2many('account.tax',
                         'proforma_invoice_line_tax',
                         'proforma_invoice_line_id',
                         'tax_id',
                         'Taxes',
                         domain=[('parent_id', '=', False)]),
        'quantity':
        fields.float(
            'Quantity',
            digits_compute=dp.get_precision('Product Unit of Measure'),
            required=True),
        'company_id':
        fields.related('invoice_id',
                       'company_id',
                       type='many2one',
                       relation='res.company',
                       string='Company',
                       store=True,
                       readonly=True),
        'partner_id':
        fields.related('invoice_id',
                       'partner_id',
                       type='many2one',
                       relation='res.partner',
                       string='Partner',
                       store=True)
    }

    _defaults = {
        'quantity': 1,
        'price_unit': 0.0,
        'sequence': 10,
    }
Beispiel #6
0
class formulir_1111(osv.osv):
    _name = 'pajak.formulir_1111'
    _description = 'SPT Masa PPN'
    _inherit = ['mail.thread']

    def default_state(self, cr, uid, context={}):
        return 'draft'

    def default_name(self, cr, uid, context={}):
        return '/'

    def default_company_id(self, cr, uid, context={}):
        #TODO : Ticket #29
        obj_res_company = self.pool.get('res.company')

        company_id = obj_res_company._company_default_get(cr,
                                                          uid,
                                                          'res.partner',
                                                          context=context)

        return company_id

    def default_created_time(self, cr, uid, context={}):
        #TODO: Ticket #30
        return datetime.now().strftime('%Y-%m-%d')

    def default_created_user_id(self, cr, uid, context={}):
        return uid

    _columns = {
        'name':
        fields.char(string='# SPT', size=30, required=True, readonly=True),
        'company_id':
        fields.many2one(obj='res.company', string='Nama PKP', required=True),
        'company_npwp':
        fields.char(string='NPWP', size=30, required=True),
        'company_address':
        fields.char(string='Alamat', size=255, required=True),
        'masa_pajak_id':
        fields.many2one(string='Masa Pajak',
                        obj='pajak.masa_pajak',
                        required=True),
        'tahun_pajak_id':
        fields.related('masa_pajak_id',
                       'tahun_pajak_id',
                       string='Tahun Pajak',
                       type='many2one',
                       relation='pajak.tahun_pajak',
                       store=True),
        'telepon':
        fields.char(string='Telepon', size=100),
        'hp':
        fields.char(string='HP', size=100),
        'klu':
        fields.char(string='KLU', size=100),
        'note':
        fields.text(string='Note'),
        'pembetulan_ke':
        fields.integer(string='Pembetulan Ke'),
        'wajib_ppnbm':
        fields.boolean(string='Wajib PPnBM'),
        # BAGIAN 1
        'item1A1':
        fields.float(string='1. Export',
                     digits_compute=dp.get_precision('Account')),
        'item1A2_dpp':
        fields.float(
            string='2. Penyerahan yang PPN-nya harus dipungut sendiri',
            digits_compute=dp.get_precision('Account')),
        'item1A2_ppn':
        fields.float(
            string='2. Penyerahan yang PPN-nya harus dipungut sendiri',
            digits_compute=dp.get_precision('Account')),
        'item1A3_dpp':
        fields.float(
            string='3. Penyerahan yang PPN-nya dipungut oleh pemungut PPN',
            digits_compute=dp.get_precision('Account')),
        'item1A3_ppn':
        fields.float(
            string='3. Penyerahan yang PPN-nya dipungut oleh pemungut PPN',
            digits_compute=dp.get_precision('Account')),
        'item1A4_dpp':
        fields.float(string='4. Penyerahan yang PPN-nya tidak dipungut',
                     digits_compute=dp.get_precision('Account')),
        'item1A4_ppn':
        fields.float(string='4. Penyerahan yang PPN-nya tidak dipungut',
                     digits_compute=dp.get_precision('Account')),
        'item1A5_dpp':
        fields.float(string='4. Penyerahan yang dibebankan dari pengenaan PPN',
                     digits_compute=dp.get_precision('Account')),
        'item1A5_ppn':
        fields.float(string='4. Penyerahan yang dibebankan dari pengenaan PPN',
                     digits_compute=dp.get_precision('Account')),
        'item_jumlah_1A':
        fields.float(string='Jumlah (I.A.1 + I.A.2 + I.A.3 + I.A.4 + I.A.5',
                     digits_compute=dp.get_precision('Account')),
        'item1B':
        fields.float(string='Tidak Terutang PPN',
                     digits_compute=dp.get_precision('Account')),
        'item1C':
        fields.float(string='Jumlah Seluruh Penyerahan (I.A + I.B)',
                     digits_compute=dp.get_precision('Account')),
        # BAGIAN 2
        'item2A':
        fields.float(string='Pajak keluaran yang harus dipungut sendiri',
                     digits_compute=dp.get_precision('Account')),
        'item2B':
        fields.float(string='PPN disetor dimuka dalam masa pajak yang sama',
                     digits_compute=dp.get_precision('Account')),
        'item2C':
        fields.float(string='Pajak masukan yang dapat diperhitungkan',
                     digits_compute=dp.get_precision('Account')),
        'item2D':
        fields.float(
            string='PPN kurang atau (lebih) bayar (II.A - II.B - II.C)',
            digits_compute=dp.get_precision('Account')),
        'item2E':
        fields.float(
            string='PPN kurang atau (lebih) bayar pada SPT yang dibetulkan',
            digits_compute=dp.get_precision('Account')),
        'item2F':
        fields.float(
            string=
            'PPN kurang atau (lebih) bayar karena pembetulan (II.D - II.E)',
            digits_compute=dp.get_precision('Account')),

        # BAGIAN 3
        'item3A':
        fields.float(string='A. Jumlah Dasar Pengenaan Pajak',
                     digits_compute=dp.get_precision('Account')),
        'item3B':
        fields.float(string='B. PPN Terutang',
                     digits_compute=dp.get_precision('Account')),
        'item3C_tanggal':
        fields.date(string='C. Dilunasi Tanggal'),
        'item3C_ntpn':
        fields.char(string='NTPN', size=100),

        # BAGIAN 4
        'item4A':
        fields.float(string='A. PPN yang wajib dibayar kembali',
                     digits_compute=dp.get_precision('Account')),
        'item4B_tanggal':
        fields.date(string='B. Dilunasi Tanggal'),
        'item4B_ntpn':
        fields.char(string='NTPN', size=100),

        # BAGIAN 5
        'item5A':
        fields.float(string='A. PPnBM yang harus dipungut kembali',
                     digits_compute=dp.get_precision('Account')),
        'item5B':
        fields.float(
            string='B. PPnBM disetor dimuka dalam Masa Pajak yang sama',
            digits_compute=dp.get_precision('Account')),
        'item5C':
        fields.float(string='C. PPnBM kurang atau (lebih) bayar (V.A - V.B)',
                     digits_compute=dp.get_precision('Account')),
        'item5D':
        fields.float(
            string=
            'D. PPnBM kurang atau (lebih) bayar pada SPT yang dibetulkan',
            digits_compute=dp.get_precision('Account')),
        'item5E':
        fields.float(
            string=
            'E. PPnBM kurang atau (lebih) bayar karena pembetulan (V.C - V.D)',
            digits_compute=dp.get_precision('Account')),
        'item5F_tanggal':
        fields.date(string='F. Dilunasi Tanggal'),
        'item5F_ntpn':
        fields.char(string='NTPN', size=100),

        # BAGIAN 6

        # PERNYATAAN
        'kota_pernyataan':
        fields.char(string='Kota', size=100, required=True),
        'tanggal_pernyataan':
        fields.date(string='Tanggal', required=True),
        'pernyataan_user_id':
        fields.many2one(string='Pengurus/Kuasa',
                        obj='res.users',
                        required=True),
        'jenis_pengurus':
        fields.selection(string='PKP/Kuasa',
                         selection=[('pkp', 'PKP'), ('kuasa', 'Kuasa')],
                         required=True),
        'state':
        fields.selection([('draft', 'Draft'),
                          ('confirm', 'Waiting For Approval'),
                          ('approve', 'Ready To Process'), ('done', 'Done'),
                          ('cancel', 'Cancel')],
                         'Status',
                         readonly=True),
        'created_time':
        fields.datetime(string='Created Time', readonly=True),
        'created_user_id':
        fields.many2one(string='Created By', obj='res.users', readonly=True),
        'confirmed_time':
        fields.datetime(string='Confirmed Time', readonly=True),
        'confirmed_user_id':
        fields.many2one(string='Confirmed By', obj='res.users', readonly=True),
        'approved_time':
        fields.datetime(string='Approved Time', readonly=True),
        'approved_user_id':
        fields.many2one(string='Approved By', obj='res.users', readonly=True),
        'processed_time':
        fields.datetime(string='Processed Time', readonly=True),
        'processed_user_id':
        fields.many2one(string='Process By', obj='res.users', readonly=True),
        'cancelled_time':
        fields.datetime(string='Processed Time', readonly=True),
        'cancelled_user_id':
        fields.many2one(string='Process By', obj='res.users', readonly=True),
        'cancelled_reason':
        fields.text(string='Cancelled Reason', readonly=True),
    }

    _defaults = {
        'name': default_name,
        'company_id': default_company_id,
        'state': default_state,
        'created_time': default_created_time,
        'created_user_id': default_created_user_id,
    }

    def workflow_action_confirm(self, cr, uid, ids, context={}):
        for id in ids:
            self.write(cr, uid, [id], {'state': 'confirm'})
        return True

    def workflow_action_approve(self, cr, uid, ids, context={}):
        for id in ids:
            self.write(cr, uid, [id], {'state': 'approve'})
        return True

    def workflow_action_done(self, cr, uid, ids, context={}):
        for id in ids:
            self.write(cr, uid, [id], {'state': 'done'})
        return True

    def workflow_action_cancel(self, cr, uid, ids, context={}):
        for id in ids:
            self.write(cr, uid, [id], {'state': 'cancel'})
        return True

    def button_action_set_to_draft(self, cr, uid, ids, context={}):
        for id in ids:
            if not self.delete_workflow_instance(self, cr, uid, id):
                return False

            if not self.create_workflow_instance(self, cr, uid, id):
                return False

        return True

    def button_action_cancel(self, cr, uid, ids, context={}):
        wkf_service = netsvc.LocalService('workflow')
        for id in ids:
            if not self.delete_workflow_instance(self, cr, uid, id):
                return False

            if not self.create_workflow_instance(self, cr, uid, id):
                return False

            wkf_service.trg_validate(uid, 'pajak.formulir_1111', id,
                                     'button_cancel', cr)

        return True

    def log_audit_trail(self, cr, uid, id, event):
        #TODO: Ticket #31
        if state not in [
                'created', 'confirmed', 'approved', 'processed', 'cancelled'
        ]:
            raise osv.except_osv(_('Peringatan!'),
                                 _('Error pada method log_audit'))
            return False

            state_dict = {
                'created': 'draft',
                'confirmed': 'confirm',
                'approved': 'approve',
                'processed': 'done',
                'cancelled': 'cancel'
            }

            val = {
                '%s_user_id' % (state): uid,
                '%s_time' % (state):
                datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'state': state_dict.get(state, False),
            }

            self.write(cr, uid, [id], val)
        return True

    def delete_workflow_instance(self, cr, uid, id):
        #TODO: Ticket #32
        wkf_service = netsvc.LocalService('workflow')

        wkf_service.trg_delete(uid, 'pajak.formulir_1111', id, cr)
        return True

    def create_workflow_instance(self, cr, uid, id):
        #TODO: Ticket #33
        wkf_service = netsvc.LocalService('workflow')

        wkf_service.trg_create(uid, 'pajak.formulir_1111', id, cr)
        return True
Beispiel #7
0
		cur_obj = self.pool.get('res.currency')
		#import pdb;pdb.set_trace()
		for line in self.browse(cr, uid, ids):
			#price = line.price_unit * (1-(line.discount or 0.0)/100.0)
			price = round(line.price_unit *line.quantity,3)
			# taxes = tax_obj.compute_all(cr, uid, line.invoice_line_tax_id, price, line.quantity, product=line.product_id, partner=line.invoice_id.partner_id)
			taxes = tax_obj.compute_all(cr, uid, line.invoice_line_tax_id, price, line.quantity, product=line.product_id, partner=line.invoice_id.partner_id)
			#res[line.id] = taxes['total']
			res[line.id] = price
			# if line.invoice_id:
			# 	cur = line.invoice_id.currency_id
			# 	res[line.id] = cur_obj.round(cr, uid, cur, res[line.id])
		return res

	_columns = {
		'quantity2': fields.float('Small Qty', digits_compute= dp.get_precision('Product Unit of Measure')),
		'uom_id' : fields.many2one('product.uom', 'Small UoM', ondelete='set null', select=True,required=True),
		'disc_tot': fields.float('Disc Total'),
		'price_subtotal': fields.function(_amount_line, string='Amount', type="float",
			digits_compute= dp.get_precision('Account'), store=True),
		'qty_func': fields.function(_get_tot_qty,string='Qty Tot'),
		'qty': fields.float('Qty', digits_compute= dp.get_precision('Product Unit of Measure')),
		'quantity': fields.function(_get_tot_qty,string='Quantity',type="float", digits_compute= dp.get_precision('Product Unit of Measure'), required=True),
		'price_unit2': fields.float('Price Unit 2'),
		'quantity3' : fields.float('Quantity PO'),

	}

	_defaults = {
		'uom_id' : _get_uom_id,
		} 
Beispiel #8
0
class WizSaleDiscount(models.TransientModel):
    _name = 'wiz.sale.discount'
    _description = 'Apply discount to sale orders'

    name = fields.Char(string='Name')
    discount_type = fields.Selection(selection=[
        ('percent_line', 'Discount rate per line'),
        ('percent_total', 'Total discount percent'),
        ('quantity_total', 'Total discount quantity')
    ],
                                     string='Discount type',
                                     default='percent_line',
                                     required=True)
    discount_applied = fields.Float(
        string='Discount applied (%)',
        digits_compute=dp.get_precision('Sale price'))
    product_id = fields.Many2one(comodel_name='product.product',
                                 string='Discount product')
    discount_quantity = fields.Float(string='Discount quantity')
    discount_taxes = fields.Many2many(comodel_name='account.tax',
                                      relation='sale_disc2tax_rel',
                                      column1='sale_discount_id',
                                      column2='tax_id',
                                      string='Discount taxes')

    @api.multi
    def button_accept(self):
        orders = self.env['sale.order'].browse(
            self.env.context.get('active_ids', []))
        for order in orders:
            if order.state != 'draft':
                raise exceptions.Warning(
                    _('The discount can only be applied when sale orders are in '
                      '\'Draft\' state.'))
            if self.discount_type == 'percent_line':
                [
                    line.write({'discount': self.discount_applied})
                    for line in order.order_line
                ]
                order.button_dummy()
                continue
            if self.discount_type == 'percent_total':
                if self.discount_applied > 100 or self.discount_applied < 0:
                    raise exceptions.Warning(
                        _('The applied discount must be between 0 and 100'))
            discount = order.amount_untaxed * (self.discount_applied / 100.0)
            price_unit = (-self.discount_quantity if self.discount_type
                          == 'quantity_total' else -discount)
            line = self.env['sale.order.line'].create({
                'order_id':
                order.id,
                'product_id':
                self.product_id.id,
                'name':
                _('Discount line'),
                'price_unit':
                price_unit,
                'tax_id': [(6, 0, [tax.id for tax in self.discount_taxes])]
            })
            order.button_dummy()
        return {'type': 'ir.actions.act_window_close'}

    @api.onchange('product_id')
    def product_id_change(self):
        if self.product_id:
            self.discount_taxes = self.product_id.taxes_id
Beispiel #9
0
									WHERE rel.invoice_id = ANY(%s)""", (list(ids),))
		return [i[0] for i in cr.fetchall()]

	_name = 'sale.order.line'
	_description = 'Sales Order Line'
	_columns = {
		'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
		'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}),
		'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."),
		'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
		'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
		'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean',
			store={
				'account.invoice': (_order_lines_from_invoice, ['state'], 10),
				'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10)}),
		'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}),
		'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
		 help="From stock: When needed, the product is taken from the stock or we wait for replenishment.\nOn order: When needed, the product is purchased or produced."),
		'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')),
		'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}),
		'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner',help="A partner to whom the particular product needs to be allotted."),
		'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product UoS'), required=True, readonly=True, states={'draft': [('readonly', False)]}),
		'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True, readonly=True, states={'draft': [('readonly', False)]}),
		'product_uos_qty': fields.float('Quantity (UoS)' ,digits_compute= dp.get_precision('Product UoS'), readonly=True, states={'draft': [('readonly', False)]}),
		'product_uos': fields.many2one('product.uom', 'Product UoS'),
		'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount'), readonly=True, states={'draft': [('readonly', False)]}),
		'th_weight': fields.float('Weight', readonly=True, states={'draft': [('readonly', False)]}),
		'state': fields.selection([('cancel', 'Cancelled'),('draft', 'Draft'),('confirmed', 'Confirmed'),('exception', 'Exception'),('done', 'Done')], 'Status', required=True, readonly=True,
				help='* The \'Draft\' status is set when the related sales order in draft status. \
					\n* The \'Confirmed\' status is set when the related sales order is confirmed. \
					\n* The \'Exception\' status is set when the related sales order is set as exception. \
Beispiel #10
0
#            ('confirm', 'Waiting Approval'),   = deducted in budget
#            ('accepted', 'Approved'),          = deducted in budget
#            ('done', 'Waiting Payment'),       = deducted in budget 
#            ('paid', 'Paid'),                  = deducted in budget + cash
            
#Totals
            res[company.id]['smart_cash'] = round(res[company.id]['smart_cash'] - res[company.id]['smart_amount_cash'],0)
            res[company.id]['smart_budget'] = round(res[company.id]['smart_budget']  - res[company.id]['smart_amount_budget'],0)

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

    _columns = {
       'smart_budget': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Budget',multi='all',help="Approved invoiced amount.",),
#       'smart_cash': fields.function(smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Budget',
#            help="Approved invoiced amount.",
#            multi='all',),
       'smart_cash': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Cash',
            help="Free invoiced amount for salary or expenses.",
            multi='all',),
        'prepayment': fields.boolean('Prepayment',help="SMart User: this virtual company can have prepayment smart_cash, SMart Company: this country applies prepayment"),
        'prepayment_days': fields.integer('Prepayment Days',help="Leadtime in days before invoiced amount becomes smart_cash (global)"),
        'smart_share': fields.float('SMarts Share',digits_compute=dp.get_precision('Account')),
        'sale_order_sum_cash': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Order sum cash',multi='all',help="Approved invoiced amount.",),
        'sale_order_sum_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Order sum budget',multi='all',help="Approved invoiced amount.",),
        'smart_amount_cash':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Amount cash',multi='all',help="Approved invoiced amount.",),
        'smart_amount_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Amount budget',multi='all',help="Approved invoiced amount.",),
        'activity_amount_cash':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart activity amount cash',multi='all',help="Approved invoiced amount.",),
        'activity_amount_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart activity amount budget',multi='all',help="Approved invoiced amount.",),
class ProductTemplate(models.Model):
    _inherit = 'product.template'

    # Column Section
    coeff1_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 1')
    incl_in_standard_price_1 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")
    coeff2_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 2')
    incl_in_standard_price_2 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")
    coeff3_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 3')
    incl_in_standard_price_3 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")
    coeff4_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 4')
    incl_in_standard_price_4 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")
    coeff5_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 5')
    incl_in_standard_price_5 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")
    coeff6_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 6')
    incl_in_standard_price_6 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")
    coeff7_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 7')
    incl_in_standard_price_7 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")
    coeff8_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 8')
    incl_in_standard_price_8 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")
    coeff9_id = fields.Many2one(comodel_name='product.coefficient',
                                string='Coefficient 9')
    incl_in_standard_price_9 = fields.Boolean("Include in Standard Price",
                                              default=False,
                                              help="""If you check this
        box, this coefficient will be used to calculate the standard price of
        the product""")

    base_price = fields.Float(
        string='Base Price',
        compute='_compute_base_price',
        store=True,
        digits=dp.get_precision('Product Price'),
        help="Base Price is the Sale Price of your Supplier.\n"
        "If product is sold by many suppliers, the first one is selected.\n"
        "If a supplier sell the product with different prices, the bigger"
        " price is used.\n\n"
        "If The supplier info belong an end date, the base price will be"
        " updated nightly, by a cron task.")

    alternative_base_price_sale = fields.Float(
        string='Alternative Base Price for Sale Price',
        help="This alternative base price will be used instead of the Base"
        " Price, if defined.")

    alternative_base_price_standard = fields.Float(
        string='Alternative Base Price for Standard Price',
        help="This alternative base price will be used instead of the Base"
        " Price, if defined.")

    coeff1_inter = fields.Float(string='With Coefficient 1',
                                compute='_compute_coeff1_inter',
                                store=True,
                                multi="coeff_inter_1")
    coeff2_inter = fields.Float(string='With Coefficient 2',
                                compute='_compute_coeff2_inter',
                                store=True,
                                multi="coeff_inter_2")
    coeff3_inter = fields.Float(string='With Coefficient 3',
                                compute='_compute_coeff3_inter',
                                store=True,
                                multi="coeff_inter_3")
    coeff4_inter = fields.Float(string='With Coefficient 4',
                                compute='_compute_coeff4_inter',
                                store=True,
                                multi="coeff_inter_4")
    coeff5_inter = fields.Float(string='With Coefficient 5',
                                compute='_compute_coeff5_inter',
                                store=True,
                                multi="coeff_inter_5")
    coeff6_inter = fields.Float(string='With Coefficient 6',
                                compute='_compute_coeff6_inter',
                                store=True,
                                multi="coeff_inter_6")
    coeff7_inter = fields.Float(string='With Coefficient 7',
                                compute='_compute_coeff7_inter',
                                store=True,
                                multi="coeff_inter_7")
    coeff8_inter = fields.Float(string='With Coefficient 8',
                                compute='_compute_coeff8_inter',
                                store=True,
                                multi="coeff_inter_8")
    coeff9_inter = fields.Float(string='With Coefficient 9',
                                compute='_compute_coeff9_inter',
                                store=True,
                                multi="coeff_inter_9",
                                digits=dp.get_precision('Product Price'))

    coeff1_inter_sp = fields.Float(string='With Supplier Discount Coefficient',
                                   compute='_compute_coeff1_inter',
                                   store=True,
                                   multi="coeff_inter_1")
    coeff2_inter_sp = fields.Float(string='With Shipping Coefficient',
                                   compute='_compute_coeff2_inter',
                                   store=True,
                                   multi="coeff_inter_2")
    coeff3_inter_sp = fields.Float(string='With Loss Coefficient',
                                   compute='_compute_coeff3_inter',
                                   store=True,
                                   multi="coeff_inter_3")
    coeff4_inter_sp = fields.Float(string='With Coefficient 4',
                                   compute='_compute_coeff4_inter',
                                   store=True,
                                   multi="coeff_inter_4")
    coeff5_inter_sp = fields.Float(string='With Coefficient 5',
                                   compute='_compute_coeff5_inter',
                                   store=True,
                                   multi="coeff_inter_5")
    coeff6_inter_sp = fields.Float(string='With Coefficient 6',
                                   compute='_compute_coeff6_inter',
                                   store=True,
                                   multi="coeff_inter_6")
    coeff7_inter_sp = fields.Float(string='With Coefficient 7',
                                   compute='_compute_coeff7_inter',
                                   store=True,
                                   multi="coeff_inter_7")
    coeff8_inter_sp = fields.Float(string='With Coefficient 8',
                                   compute='_compute_coeff8_inter',
                                   store=True,
                                   multi="coeff_inter_8")
    coeff9_inter_sp = fields.Float(string='With Margin Coefficient',
                                   compute='_compute_coeff9_inter',
                                   store=True,
                                   multi="coeff_inter_9",
                                   digits=dp.get_precision('Product Price'))

    theoritical_price = fields.Float(string='Theoritical Price VAT Incl.',
                                     compute='_compute_theoritical_price',
                                     store=True,
                                     digits=dp.get_precision('Product Price'))

    has_theoritical_price_different = fields.Boolean(
        string='Has Theoritical Price Different',
        store=True,
        compute='_compute_has_theoritical_price_different')

    has_theoritical_cost_different = fields.Boolean(
        string='Has Theoritical Cost Different',
        store=True,
        compute='_compute_has_theoritical_cost_different')

    # Custom Section
    @api.multi
    def recompute_base_price(self):
        self._compute_base_price()

    @api.multi
    def use_theoritical_price(self):
        for template in self:
            template.list_price = template.theoritical_price
        return True

    @api.multi
    def use_theoritical_cost(self):
        for template in self:
            template.standard_price = template.coeff9_inter_sp
        return True

    @api.model
    def cron_recompute_base_price(self):
        auto_update_base_price = self.get_auto_update_base_price()
        if auto_update_base_price:
            templates = self.search([])
            templates.recompute_base_price()

    # Compute Section
    @api.multi
    @api.depends('product_variant_ids', 'uom_id', 'uom_po_id',
                 'seller_ids.price', 'seller_ids.product_uom',
                 'seller_ids.discount')
    def _compute_base_price(self):
        # TODO IMPME. Compute with discount, depending on
        # product_supplierinfo_discount
        product_obj = self.env['product.product']
        for template in self:
            base_price = 0.0
            if template.product_variant_ids:
                # We set a high quantity to avoid to skip
                seller = product_obj._select_seller(
                    template.product_variant_ids[0], quantity=10000.0)
                if seller:
                    if seller.product_uom.id == template.uom_id.id:
                        base_price =\
                            seller.price * (100 - seller.discount) / 100
                    else:
                        base_price = (
                            (seller.price / seller.product_uom.factor_inv) *
                            template.uom_id.factor_inv *
                            (100 - seller.discount) / 100)
            template.base_price = base_price

    @api.multi
    @api.depends('alternative_base_price_standard',
                 'alternative_base_price_sale', 'base_price',
                 'coeff1_id.operation_type', 'coeff1_id.value',
                 'incl_in_standard_price_1')
    def _compute_coeff1_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            if template.alternative_base_price_sale:
                base_price_sale = template.alternative_base_price_sale
            else:
                base_price_sale = template.base_price
            if template.alternative_base_price_standard:
                base_price_standard = template.alternative_base_price_standard
            else:
                base_price_standard = template.base_price
            template.coeff1_inter = coefficient_obj.compute_price(
                template.coeff1_id, base_price_sale)
            if template.incl_in_standard_price_1:
                template.coeff1_inter_sp = coefficient_obj.compute_price(
                    template.coeff1_id, base_price_standard)
            else:
                template.coeff1_inter_sp = base_price_standard

    @api.multi
    @api.depends('coeff1_inter', 'coeff2_id.operation_type', 'coeff2_id.value',
                 'incl_in_standard_price_2')
    def _compute_coeff2_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            template.coeff2_inter = coefficient_obj.compute_price(
                template.coeff2_id, template.coeff1_inter)
            if template.incl_in_standard_price_2:
                template.coeff2_inter_sp = coefficient_obj.compute_price(
                    template.coeff2_id, template.coeff1_inter_sp)
            else:
                template.coeff2_inter_sp = template.coeff1_inter_sp

    @api.multi
    @api.depends('coeff2_inter', 'coeff3_id.operation_type', 'coeff3_id.value',
                 'incl_in_standard_price_3')
    def _compute_coeff3_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            template.coeff3_inter = coefficient_obj.compute_price(
                template.coeff3_id, template.coeff2_inter)
            if template.incl_in_standard_price_3:
                template.coeff3_inter_sp = coefficient_obj.compute_price(
                    template.coeff3_id, template.coeff2_inter_sp)
            else:
                template.coeff3_inter_sp = template.coeff2_inter_sp

    @api.multi
    @api.depends('coeff3_inter', 'coeff4_id.operation_type', 'coeff4_id.value',
                 'incl_in_standard_price_4')
    def _compute_coeff4_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            template.coeff4_inter = coefficient_obj.compute_price(
                template.coeff4_id, template.coeff3_inter)
            if template.incl_in_standard_price_4:
                template.coeff4_inter_sp = coefficient_obj.compute_price(
                    template.coeff4_id, template.coeff3_inter_sp)
            else:
                template.coeff4_inter_sp = template.coeff3_inter_sp

    @api.multi
    @api.depends('coeff4_inter', 'coeff5_id.operation_type', 'coeff5_id.value',
                 'incl_in_standard_price_5')
    def _compute_coeff5_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            template.coeff5_inter = coefficient_obj.compute_price(
                template.coeff5_id, template.coeff4_inter)
            if template.incl_in_standard_price_5:
                template.coeff5_inter_sp = coefficient_obj.compute_price(
                    template.coeff5_id, template.coeff4_inter_sp)
            else:
                template.coeff5_inter_sp = template.coeff4_inter_sp

    @api.multi
    @api.depends('coeff5_inter', 'coeff6_id.operation_type', 'coeff6_id.value',
                 'incl_in_standard_price_6')
    def _compute_coeff6_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            template.coeff6_inter = coefficient_obj.compute_price(
                template.coeff6_id, template.coeff5_inter)
            if template.incl_in_standard_price_6:
                template.coeff6_inter_sp = coefficient_obj.compute_price(
                    template.coeff6_id, template.coeff5_inter_sp)
            else:
                template.coeff6_inter_sp = template.coeff5_inter_sp

    @api.multi
    @api.depends('coeff6_inter', 'coeff7_id.operation_type', 'coeff7_id.value',
                 'incl_in_standard_price_7')
    def _compute_coeff7_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            template.coeff7_inter = coefficient_obj.compute_price(
                template.coeff7_id, template.coeff6_inter)
            if template.incl_in_standard_price_7:
                template.coeff7_inter_sp = coefficient_obj.compute_price(
                    template.coeff7_id, template.coeff6_inter_sp)
            else:
                template.coeff7_inter_sp = template.coeff6_inter_sp

    @api.multi
    @api.depends('coeff7_inter', 'coeff8_id.operation_type', 'coeff8_id.value',
                 'incl_in_standard_price_8')
    def _compute_coeff8_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            template.coeff8_inter = coefficient_obj.compute_price(
                template.coeff8_id, template.coeff7_inter)
            if template.incl_in_standard_price_8:
                template.coeff8_inter_sp = coefficient_obj.compute_price(
                    template.coeff8_id, template.coeff7_inter_sp)
            else:
                template.coeff8_inter_sp = template.coeff7_inter_sp

    @api.multi
    @api.depends('coeff8_inter', 'coeff9_id.operation_type', 'coeff9_id.value',
                 'incl_in_standard_price_9')
    def _compute_coeff9_inter(self):
        coefficient_obj = self.env['product.coefficient']
        for template in self:
            template.coeff9_inter = coefficient_obj.compute_price(
                template.coeff9_id, template.coeff8_inter)
            if template.incl_in_standard_price_9:
                template.coeff9_inter_sp = coefficient_obj.compute_price(
                    template.coeff9_id, template.coeff8_inter_sp)
            else:
                template.coeff9_inter_sp = template.coeff8_inter_sp

    @api.multi
    @api.depends('coeff9_inter', 'taxes_id.amount', 'taxes_id.price_include',
                 'taxes_id.amount_type')
    def _compute_theoritical_price(self):
        for template in self:
            multi = 1
            for tax in template.taxes_id:
                if tax.amount_type != 'percent' or not tax.price_include:
                    raise exceptions.UserError(
                        _("Unimplemented Feature\n"
                          "The Tax %s is not correctly set for computing"
                          " prices with coefficients for the product %s") %
                        (tax.name, template.name))
                multi *= 1 + (tax.amount / 100)
            template.theoritical_price = template.coeff9_inter * multi

    @api.multi
    @api.depends('theoritical_price', 'list_price')
    def _compute_has_theoritical_price_different(self):
        auto_update_theorical_price = self.get_auto_update_theorical_price()
        for template in self:
            if template.theoritical_price and (
                    template.base_price
                    or template.alternative_base_price_sale):
                template.has_theoritical_price_different =\
                    template.list_price != template.theoritical_price
            else:
                template.has_theoritical_price_different = False

    @api.multi
    @api.depends('coeff9_inter_sp', 'standard_price')
    def _compute_has_theoritical_cost_different(self):
        auto_update_theorical_cost = self.get_auto_update_theorical_cost()
        for template in self:
            if template.coeff9_inter_sp and (
                    template.base_price
                    or template.alternative_base_price_standard):
                template.has_theoritical_cost_different =\
                    template.standard_price != template.coeff9_inter_sp
            else:
                template.has_theoritical_cost_different = False

    @api.model
    def get_auto_update_base_price(self):
        # Get Purchase Configuration: Updates Base Price automatically
        param_env = self.env['ir.config_parameter']
        val = safe_eval(param_env.get_param('auto_update_base_price'))
        return val

    @api.model
    def get_auto_update_theorical_cost(self):
        # Get Purchase Configuration: Updates Theorical Cost automatically
        param_env = self.env['ir.config_parameter']
        val = safe_eval(param_env.get_param('auto_update_theorical_cost'))
        return val

    @api.model
    def get_auto_update_theorical_price(self):
        # Get Purchase Configuration: Updates Theorical Price automatically
        param_env = self.env['ir.config_parameter']
        val = safe_eval(param_env.get_param('auto_update_theorical_price'))
        return val

    @api.multi
    def auto_update_theoritical_cost_price(self):
        for obj in self:
            if obj.has_theoritical_cost_different and \
                    obj.get_auto_update_theorical_cost():
                obj.use_theoritical_cost()

            if obj.has_theoritical_price_different and \
                    obj.get_auto_update_theorical_price():
                obj.use_theoritical_price()

    @api.multi
    def write(self, vals):
        ret = super(ProductTemplate, self).write(vals)
        self.auto_update_theoritical_cost_price()
        return ret

    @api.model
    def create(self, vals):
        new_obj = super(ProductTemplate, self).create(vals)
        new_obj.auto_update_theoritical_cost_price()
        return new_obj
Beispiel #12
0
class delivery_route_line(osv.osv):
    _inherit = 'delivery.route.line'

    def _get_sign_paid(self, cr, uid, ids, fields_name, args, context=None):
        """
            Indica si el cliente debe pagar el pedido en caso de no contar con credito y
            muestra el botón de 'pago' si el estado de la factura es 'abierto
        """
        res = {}
        date = time.strftime('%Y-%m-%d')
        # Obtiene la configuracion
        config_obj = self.pool.get('delivery.config.settings')
        config = config_obj.get_setting_payment(cr, uid, context=context)

        # Recorremos los ids
        for id in ids:
            res[id] = {
                'paid_button_show': False,
                'paid_all_sign': False,
                'paid_cash_sign': False,
            }

            # Valida que apliquen condiciones sobre pago
            if not config['payments_enable']:
                continue

            delivery = self.read(
                cr, uid, id,
                ['credit_available', 'date_due', 'invoice_state', 'residual'])
            print "*****DATE_DUE*****: ", delivery['date_due']
            print "*****DATE*****: ", date
            # Se valida que el cliente disponga del credito para pagar y la factura no este vencida
            if delivery['credit_available'] == 0.0 and delivery[
                    'date_due'] <= date and delivery[
                        'credit_available'] < delivery['residual']:
                res[id]['paid_all_sign'] = True

            #if type_payment_term == 'cash':
            #    res[id]['paid_cash_sign'] = True

        #if type_payment_term == 'cash':
        #    self.write(cr, uid, ids, {'state': 'pending_paid'}, context=context)
        #    # Registra el log sobre la actualizacion sobre la transicion de estado
        #    self.pool.get('delivery.route.line.log').add_log_route_line(cr, uid, ids, state='pending_paid', context=context)

        # Se valida si existe un pago pendiente
            if delivery['residual'] > 0.0:
                res[id]['paid_button_show'] = True
        return res

    _columns = {
        'residual':
        fields.related('invoice_id',
                       'residual',
                       type='float',
                       digits_compute=dp.get_precision('Delivery'),
                       string="Monto a pagar"),
        'date_invoice':
        fields.related('invoice_id',
                       'date_invoice',
                       type='date',
                       string="Fecha factura"),
        'date_due':
        fields.related('invoice_id',
                       'date_due',
                       type='date',
                       string="Fecha vencimiento"),
        'payment_term':
        fields.related('invoice_id',
                       'payment_term',
                       type='many2one',
                       relation='account.payment.term',
                       string="Plazo de pago"),
        'state':
        fields.selection(
            [('draft', 'No planeado'), ('planned', 'Planeado'),
             ('open', 'Por surtir'), ('pending_paid', 'Esperando pago'),
             ('arrived', 'Arribado'), ('delivered', 'En entrega'),
             ('delivered_carrier', 'En entrega transportista'),
             ('exeption', 'Excepcion entrega'), ('done', 'Entregado'),
             ('pending_paid_delivered', 'Esperando pago de entrega'),
             ('pending_credit', 'Autorizacion credito'), ('paid', 'pagado'),
             ('not_found', 'No encontrado'), ('return', 'Devuelto'),
             ('picking', 'Entregado Almacen'), ('cancel', 'Cancelado')],
            string='Estado entrega',
            store=True,
            readonly=True),
        'credit_available':
        fields.related('address_id',
                       'credit_available',
                       type="float",
                       string="Credito disponible",
                       digits_compute=dp.get_precision('Delivery')),
        'paid_button_show':
        fields.function(_get_sign_paid,
                        type='boolean',
                        string="Mostrar boton pago",
                        store=False,
                        multi='paid'),
        'paid_all_sign':
        fields.function(_get_sign_paid,
                        type='boolean',
                        string="Pagar todo",
                        store=False,
                        multi='paid'),
        'pending_credit':
        fields.boolean('solicito credito?')
    }

    def action_paid(self, cr, uid, ids, context=None):
        """
            Abre el wizard para realizar el pago además de pasar el pedido al estado 'En entrega'
        """
        #paid_obj = self.pool.get('paid.manager.wizard')
        move = self.browse(cr, uid, ids[0], context=context)
        invoice = move.invoice_id
        residual = move.residual
        route_id = move.route_id.id or False

        dummy, view_id = self.pool.get('ir.model.data').get_object_reference(
            cr, uid, 'delivery_plan', 'paid_manager_wizard')
        return {
            'name': 'Pagar factura',
            'view_type': 'form',
            'view_mode': 'form',
            'view_id': view_id,
            'res_model': 'paid.manager.wizard',
            'target': 'new',
            'context': context,
            'type': 'ir.actions.act_window',
            'nodestroy': True,
            #'res_id': paid_id
            'context': {
                #'payment_expected_currency': invoice.currency_id.id,
                'default_partner_id':
                self.pool.get('res.partner')._find_accounting_partner(
                    invoice.partner_id).id,
                'default_amount':
                invoice.type in ('out_refund', 'in_refund') and -residual
                or residual,
                'default_reference':
                invoice.name,
                #'close_after_process': True,
                #'invoice_type': invoice.type,
                'default_invoice_id':
                invoice.id,
                'default_route_id':
                route_id,
                #'default_type': invoice.type in ('out_invoice','out_refund') and 'receipt' or 'payment',
                #'type': invoice.type in ('out_invoice','out_refund') and 'receipt' or 'payment'
            }
        }

    def action_arrived(self, cr, uid, ids, context=None):
        """
            Pasa la entrega a estado arrivado validando que el tipo de pago no sea de contado
        """
        type_payment_term = self.browse(cr, uid, ids[0],
                                        context=context).payment_term.type
        #print "******TYPE_PAYMENT_TERM*****: ", type_payment_term

        super(delivery_route_line, self).action_arrived(cr,
                                                        uid,
                                                        ids,
                                                        context=context)
        return True

    #def action_done(self, cr, uid, ids, context=None):
    #    """
    #        Valida si hay algun adedudo una vez entregado el producto, en caso de haberlo se realiza el cobro
    #    """
    #    super(delivery_route_line, self). action_done(cr, uid, ids, context=context)
    #
    #    move = self.browse(cr, uid, ids[0], context=context)
    #    if move.residual > 0:
    #        self.write(cr, uid, ids, {'state': 'pending_paid_delivered'}, context=context)
    #        # Registra el log sobre la actualizacion sobre la transicion de estado
    #        self.pool.get('delivery.route.line.log').add_log_route_line(cr, uid, ids, state='pending_paid_delivered', context=context)
    #        return True
    #    else:
    #        return True

    def action_requisition_credit_new(self, cr, uid, ids, context=None):
        """
            Permite realizar una solicitud de credito
        """
        if context is None:
            context = {}

        #if self.browse(cr,uid,ids[0], context=context).pending_credit == False:
        #    self.write(cr, uid, ids, {'state': 'pending_credit', 'pending_credit': True}, context=context)
        #    # Registra el log sobre la actualizacion sobre la transicion de estado
        #    self.pool.get('delivery.route.line.log').add_log_route_line(cr, uid, ids, state='pending_credit', context=context)

        # Obtiene la vista a cargar
        if not ids: return []
        dummy, view_id = self.pool.get('ir.model.data').get_object_reference(
            cr, uid, 'requisition_credit',
            'requisition_credit_credit_new_form_view')

        route_line = self.browse(cr, uid, ids[0], context=context)

        # Obtiene los parametros que van por default
        context[
            'default_partner_id'] = route_line.invoice_id.partner_id.id or False
        context['default_rfc'] = route_line.invoice_id.partner_id.rfc
        context[
            'default_current_credit'] = route_line.invoice_id.partner_id.credit_limit
        context['default_user_id'] = uid
        context['default_state'] = 'open'

        return {
            'name': _("Solicitud de credito"),
            'view_mode': 'form',
            'view_id': view_id,
            'view_type': 'form',
            'res_model': 'requisition.credit.credit',
            'type': 'ir.actions.act_window',
            'nodestroy': True,
            'target': 'current',
            'domain': '[]',
            'context': context
        }
Beispiel #13
0
class account_wh_src(osv.osv):

    def name_get(self, cursor, user, ids, context=None):
        """ To generate a name for src record
        """
        if isinstance(ids, (int, long)):
            ids = [ids]
        if not ids:
            return []
        res = []
        data_move = self.pool.get('account.wh.src').browse(
            cursor, user, ids, context=context)
        for move in data_move:
            if not move.name:
                if move.number:
                    name = move.number
                else:
                    name = 'CRS * ID = ' + str(move.id)
            else:
                name = move.name
            res.append((move.id, name))
        return res

    def _get_uid_wh_agent(self, cr, uid, context=None):
        """ Return true if current partner is social responsability agent and
        return false in otherwise
        """
        context = context or {}
        rp_obj = self.pool.get('res.partner')
        ru_obj = self.pool.get('res.users')
        ru_brw = ru_obj.browse(cr, uid, uid, context=context)
        acc_part_brw = rp_obj._find_accounting_partner(
            ru_brw.company_id.partner_id)
        return acc_part_brw.wh_src_agent

    def _get_partner_agent(self, cr, uid, context=None):
        """ Return a list of browse partner depending of invoice type
        """
        obj_partner = self.pool.get('res.partner')
        args = [('parent_id', '=', False)]
        context = context or {}
        res = []

        if context.get('type') in ('out_invoice',):
            args.append(('wh_src_agent', '=', True))
        partner_ids = obj_partner.search(cr, uid, args)
        if partner_ids:
            partner_brw = obj_partner.browse(
                cr, uid, partner_ids, context=context)
            res = [item.id for item in partner_brw]
        return res

    def default_get(self, cr, uid, field_list, context=None):
        """ Update fields uid_wh_agent and partner_list to the create a
        record
        """
        # NOTE: use field_list argument instead of fields for fix the pylint
        # error W0621 Redefining name 'fields' from outer scope
        context = context or {}
        res = super(account_wh_src, self).default_get(
            cr, uid, field_list, context=context)
        res.update({'uid_wh_agent': self._get_uid_wh_agent(
            cr, uid, context=context)})
        res.update({'partner_list': self._get_partner_agent(
            cr, uid, context=context)})

        return res

    def _get_p_agent(self, cr, uid, ids, field_name, args, context=None):
        """ Create a dictionary with ids partner and their browse item
        """
        context = context or {}
        res = {}.fromkeys(ids, self._get_partner_agent(
            cr, uid, context=context))
        return res

    def _get_wh_agent(self, cr, uid, ids, field_name, args, context=None):
        """ Create a dictionary with ids agent partner and their browse item
        """
        context = context or {}
        res = {}.fromkeys(ids, self._get_uid_wh_agent(cr, uid,
                                                      context=context))
        return res

    _name = "account.wh.src"
    _description = "Social Responsibility Commitment Withholding"
    _columns = {
        'name': fields.char('Description', size=64, readonly=True,
                            states={'draft': [('readonly', False)]},
                            help="Description of withholding"),
        'code': fields.char(
            'Code', size=32, readonly=True,
            states={'draft': [('readonly', False)]},
            help="Withholding reference"),
        'number': fields.char(
            'Number', size=32, states={'draft': [('readonly', False)]},
            help="Withholding number"),
        'type': fields.selection([
            ('out_invoice', 'Customer Invoice'),
            ('in_invoice', 'Supplier Invoice'),
        ], 'Type', readonly=False, help="Withholding type"),
        'state': fields.selection([
            ('draft', 'Draft'),
            ('confirmed', 'Confirmed'),
            ('done', 'Done'),
            ('cancel', 'Cancelled')
        ], 'Estado', readonly=True, help="Status Voucher"),
        'date_ret': fields.date('Withholding date', readonly=True,
                                states={'draft': [('readonly', False)]},
                                help="Keep empty to use the current date"),
        'date': fields.date(
            'Date', readonly=True, states={'draft': [('readonly', False)]},
            help="Date"),
        'period_id': fields.many2one(
            'account.period', 'Force Period', domain=[('state', '!=', 'done')],
            readonly=True, states={'draft': [('readonly', False)]},
            help="Keep empty to use the period of the validation"
                 " (Withholding date) date."),
        'account_id': fields.many2one(
            'account.account', 'Account', required=True, readonly=True,
            states={'draft': [('readonly', False)]},
            help="The pay account used for this withholding."),
        'partner_id': fields.many2one(
            'res.partner', 'Partner', readonly=True, required=True,
            states={'draft': [('readonly', False)]},
            help="Withholding customer/supplier"),
        'currency_id': fields.many2one(
            'res.currency', 'Currency', required=True, readonly=True,
            states={'draft': [('readonly', False)]}, help="Currency"),
        'journal_id': fields.many2one(
            'account.journal', 'Journal', required=True, readonly=True,
            states={'draft': [('readonly', False)]}, help="Journal entry"),
        'company_id': fields.many2one(
            'res.company', 'Company', required=True, help="Company"),
        'line_ids': fields.one2many(
            'account.wh.src.line', 'wh_id', 'Local withholding lines',
            readonly=True, states={'draft': [('readonly', False)]},
            help="Invoices which deductions will be made"),
        'wh_amount': fields.float(
            'Amount', required=False,
            digits_compute=dp.get_precision('Withhold'),
            help="Amount withheld"),

        'uid_wh_agent': fields.function(
            _get_wh_agent, type='boolean', string="uid_wh_agent", store=False,
            help='indicates whether the current user is agent'),
        'partner_list': fields.function(
            _get_p_agent, type='char', string='Lista', store=False,
            method=False,
            help='partners are only allowed to be withholding agents'),

    }

    def _get_journal(self, cr, uid, context=None):
        """
        Return a SRC journal depending of invoice type
        """
        context = dict(context or {})
        type_inv = context.get('type', 'in_invoice')
        type2journal = {'out_invoice': 'src_sale',
                        'in_invoice': 'src_purchase'}
        journal_obj = self.pool.get('account.journal')
        user = self.pool.get('res.users').browse(
            cr, uid, uid, context=context)
        company_id = context.get('company_id', user.company_id.id)
        domain = [('company_id', '=', company_id)]
        domain += [('type', '=', type2journal.get(
            type_inv, 'src_purchase'))]
        res = journal_obj.search(cr, uid, domain, limit=1)
        return res and res[0] or False

    _defaults = {
        'state': lambda *a: 'draft',
        'currency_id':
            lambda self, cr, uid, c: self.pool.get('res.users').browse(
                cr, uid, uid, c).company_id.currency_id.id,
        'journal_id': _get_journal,
        'company_id':
            lambda self, cr, uid, c: self.pool.get('res.users').browse(
                cr, uid, uid, c).company_id.id,
    }

    _sql_constraints = [
    ]

    def onchange_partner_id(self, cr, uid, ids, inv_type, partner_id,
                            context=None):
        """ Return account depending of the invoice
        @param type: invoice type
        @param partner_id: partner id
        """
        if context is None:
            context = {}
        acc_part_brw = False
        acc_id = False
        rp_obj = self.pool.get('res.partner')
        wh_line_obj = self.pool.get('account.wh.src.line')

        if partner_id:
            acc_part_brw = rp_obj._find_accounting_partner(
                rp_obj.browse(cr, uid, partner_id))
            if inv_type in ('out_invoice', 'out_refund'):
                acc_id = acc_part_brw.property_account_receivable \
                    and acc_part_brw.property_account_receivable.id or False
            else:
                acc_id = acc_part_brw.property_account_payable \
                    and acc_part_brw.property_account_payable.id or False

        part_brw = ids and rp_obj._find_accounting_partner(self.browse(
            cr, uid, ids[0], context=context).partner_id)
        wh_lines = ids and wh_line_obj.search(cr, uid,
                                              [('wh_id', '=', ids[0])])
        if not partner_id:
            if wh_lines:
                wh_line_obj.unlink(cr, uid, wh_lines)
            wh_lines = []
        if part_brw and acc_part_brw and part_brw.id != acc_part_brw.id:
            if wh_lines:
                wh_line_obj.unlink(cr, uid, wh_lines)
            wh_lines = []

        return {'value': {
            'line_ids': wh_lines,
            'account_id': acc_id,
        }
        }

    def action_date_ret(self, cr, uid, ids, context=None):
        """ if the retention date is empty, is filled with the current date
        """
        for wh in self.browse(cr, uid, ids, context):
            if not wh.date_ret:
                self.write(cr, uid, [wh.id],
                           {'date_ret': time.strftime('%Y-%m-%d')})
        return True

    def action_draft(self, cr, uid, ids, context=None):
        """ Passes the document to draft status
        """
        context = context or {}
        inv_obj = self.pool.get('account.invoice')

        brw = self.browse(cr, uid, ids[0], context)
        inv_ids = [i.invoice_id.id for i in brw.line_ids]
        if inv_ids:
            inv_obj.write(cr, uid, inv_ids, {'wh_src_id': False})

        return self.write(cr, uid, ids[0], {'state': 'draft'})

    def action_confirm(self, cr, uid, ids, context=None):
        """ Retention is valid to pass a status confirmed
        """
        context = context or {}
        inv_obj = self.pool.get('account.invoice')

        brw = self.browse(cr, uid, ids[0], context)
        line_ids = brw.line_ids
        if not line_ids:
            raise osv.except_osv(
                _('Invalid Procedure!'), _("No retention lines"))

        res = [True]
        res += [False for i in line_ids
                if (i.wh_amount <= 0.0 or
                    i.base_amount <= 0.0 or
                    i.wh_src_rate <= 0.0)]
        if not all(res):
            raise osv.except_osv(
                _('Invalid Procedure!'),
                _("Verify retention lines not have Null values(0.00)"))

        res = 0.0
        for i in line_ids:
            res += i.wh_amount
        if abs(res - brw.wh_amount) > 0.0001:
            raise osv.except_osv(
                _('Invalid Procedure!'),
                _("Check the amount of withholdings"))

        inv_ids = [i.invoice_id.id for i in brw.line_ids]
        if inv_ids:
            inv_obj.write(cr, uid, inv_ids, {'wh_src_id': ids[0]})

        return self.write(cr, uid, ids[0], {'state': 'confirmed'})

    def action_done(self, cr, uid, ids, context=None):
        """ Pass the document to state done
        """
        if context is None:
            context = {}

        self.action_date_ret(cr, uid, ids, context=context)
        self.action_number(cr, uid, ids)
        self.action_move_create(cr, uid, ids, context=context)

        return self.write(cr, uid, ids, {'state': 'done'})

    def _dummy_cancel_check(self, cr, uid, ids, context=None):
        '''
        This will be the method that another developer should use to create new
        check on Withholding Document
        Make super to this method and create your own cases
        '''
        return True

    def cancel_check(self, cr, uid, ids, context=None):
        '''
        Unique method to check if we can cancel the Withholding Document
        '''
        context = context or {}
        ids = isinstance(ids, (int, long)) and [ids] or ids

        if not self._dummy_cancel_check(cr, uid, ids, context=context):
            return False
        return True

    def cancel_move(self, cr, uid, ids, *args):
        """ Delete move lines related with withholding vat and cancel
        """
        ids = isinstance(ids, (int, long)) and [ids] or ids
        am_obj = self.pool.get('account.move')
        for ret in self.browse(cr, uid, ids):
            if ret.state == 'done':
                for ret_line in ret.line_ids:
                    if ret_line.move_id:
                        am_obj.button_cancel(cr, uid, [ret_line.move_id.id])
                        am_obj.unlink(cr, uid, [ret_line.move_id.id])
            ret.write({'state': 'cancel'})
        return True

    def clear_wh_lines(self, cr, uid, ids, context=None):
        """ Clear lines of current withholding document and delete wh document
        information from the invoice.
        """
        context = context or {}
        awsl_obj = self.pool.get('account.wh.src.line')
        ai_obj = self.pool.get('account.invoice')
        if ids:
            awsl_ids = awsl_obj.search(cr, uid, [('wh_id', 'in', ids)],
                                       context=context)
            ai_ids = awsl_ids and [
                awsl.invoice_id.id
                for awsl in awsl_obj.browse(cr, uid, awsl_ids,
                                            context=context)]
            if ai_ids:
                ai_obj.write(cr, uid, ai_ids,
                             {'wh_src_id': False}, context=context)
            if awsl_ids:
                awsl_obj.unlink(cr, uid, awsl_ids, context=context)

        return True

    def action_cancel(self, cr, uid, ids, context=None):
        """ Call cancel_move and return True
        """
        ids = isinstance(ids, (int, long)) and [ids] or ids
        context = context or {}
        self.cancel_move(cr, uid, ids)
        self.clear_wh_lines(cr, uid, ids, context=context)
        return True

    def copy(self, cr, uid, ids, default=None, context=None):
        """ Lines can not be duplicated in this model
        """
        # NOTE: use ids argument instead of id for fix the pylint error W0622.
        # Redefining built-in 'id'
        raise osv.except_osv(
            _('Invalid Procedure!'),
            _("You can not duplicate lines"))

    def unlink(self, cr, uid, ids, context=None):
        """ Overwrite the unlink method to throw an exception if the
        withholding is not in cancel state."""
        context = context or {}
        for src_brw in self.browse(cr, uid, ids, context=context):
            if src_brw.state != 'cancel':
                raise osv.except_osv(
                    _("Invalid Procedure!!"),
                    _("The withholding document needs to be in cancel state to"
                      " be deleted."))
            else:
                super(account_wh_src, self).unlink(
                    cr, uid, ids, context=context)
        return True

    def action_move_create(self, cr, uid, ids, context=None):
        """ Build account moves related to withholding invoice
        """
        inv_obj = self.pool.get('account.invoice')
        if context is None:
            context = {}

        context.update({'wh_src': True})

        ret = self.browse(cr, uid, ids[0], context)

        for line in ret.line_ids:
            if line.move_id:
                raise osv.except_osv(
                    _('Invoice already withhold !'),
                    _("You must omit the follow invoice '%s' !") %
                    (line.invoice_id.number,))

        acc_id = ret.account_id.id

        period_id = ret.period_id and ret.period_id.id or False
        journal_id = ret.journal_id.id
        if not period_id:
            per_obj = self.pool.get('account.period')
            period_id = per_obj.find(
                cr, uid, ret.date_ret or time.strftime('%Y-%m-%d'))
            # Due to the fact that demo data for periods sets 'special' as True
            # on them, this little hack is necesary if this issue is solved we
            # should ask directly for the refer to this bug for more
            # information
            # https://bugs.launchpad.net/openobject-addons/+bug/924200
            demo_enabled = self.pool.get('ir.module.module').search(
                cr, uid, [('name', '=', 'base'), ('demo', '=', True)])
            args = [('id', 'in', period_id)]
            if not demo_enabled:
                args.append(('special', '=', False))
            period_id = per_obj.search(cr, uid, args)
            if not period_id:
                raise osv.except_osv(
                    _('Missing Periods!'),
                    _("There are not Periods created for the pointed day:"
                      " %s!") % (ret.date_ret or time.strftime('%Y-%m-%d')))
            period_id = period_id[0]
        if period_id:
            if ret.line_ids:
                for line in ret.line_ids:
                    writeoff_account_id, writeoff_journal_id = False, False
                    amount = line.wh_amount
                    if line.invoice_id.type in ['in_invoice', 'in_refund']:
                        name = 'COMP. RET. CRS ' + ret.number + ' Doc. ' + (
                            line.invoice_id.supplier_invoice_number or '')
                    else:
                        name = 'COMP. RET. CRS ' + ret.number + ' Doc. ' + (
                            line.invoice_id.number or '')
                    ret_move = inv_obj.ret_and_reconcile(
                        cr, uid, [line.invoice_id.id], amount, acc_id,
                        period_id, journal_id, writeoff_account_id, period_id,
                        writeoff_journal_id, ret.date_ret, name, [line],
                        context)
                    rl = {
                        'move_id': ret_move['move_id'],
                    }
                    lines = [(1, line.id, rl)]
                    self.write(cr, uid, [ret.id], {
                        'line_ids': lines, 'period_id': period_id})

                    if (rl and line.invoice_id.type in [
                            'out_invoice', 'out_refund']):
                        inv_obj.write(
                            cr, uid, [line.invoice_id.id],
                            {'wh_src_id': ret.id})
            else:
                return False
        return True

    def action_number(self, cr, uid, ids, *args):
        """ Is responsible for generating a number for the document if it does
        not have one
        """
        obj_ret = self.browse(cr, uid, ids)[0]
        if obj_ret.type == 'in_invoice':
            cr.execute(
                'SELECT id, number '
                'FROM account_wh_src '
                'WHERE id IN (' + ','.join([str(item) for item in ids]) + ')')

            for (aws_id, number) in cr.fetchall():
                if not number:
                    number = self.pool.get('ir.sequence').get(
                        cr, uid, 'account.wh.src.%s' % obj_ret.type)
                cr.execute('UPDATE account_wh_src SET number=%s '
                           'WHERE id=%s', (number, aws_id))

        return True

    def wh_src_confirmed(self, cr, uid, ids):
        """ Confirm src document
        """
        return True
Beispiel #14
0
class account_wh_src_line(osv.osv):

    _name = "account.wh.src.line"
    _description = "Social Responsibility Commitment Withholding Line"
    _columns = {
        'name': fields.char(
            'Description', size=64, required=True,
            help="Local Withholding line Description"),
        'wh_id': fields.many2one(
            'account.wh.src', 'Local withholding', ondelete='cascade',
            help="Local withholding"),
        'invoice_id': fields.many2one(
            'account.invoice', 'Invoice', required=True, ondelete='set null',
            help="Withholding invoice"),
        'base_amount': fields.float(
            'Base Amount',
            digits_compute=dp.get_precision('Base Amount to be Withheld'),
            help='amount to be withheld'),
        'wh_amount': fields.float(
            'Withheld Amount', digits_compute=dp.get_precision('Withhold'),
            help='withheld amount'),
        'move_id': fields.many2one(
            'account.move', 'Account Entry', readonly=True,
            help="Account Entry"),
        'wh_src_rate': fields.float(
            'Withholding Rate', help="Withholding rate"),
    }
    _defaults = {

    }
    _sql_constraints = [

    ]

    def onchange_invoice_id(self, cr, uid, ids, inv_type, invoice_id=False,
                            base_amount=0.0, wh_src_rate=5.0, context=None):
        """ Change src information to change the invoice
        @param type: invoice type
        @param invoice_id: new invoice id
        @param base_amount: new base amount
        @param wh_src_rate: new rate of the withhold src
        """
        if context is None:
            context = {}
        res = {}
        inv_obj = self.pool.get('account.invoice')
        if not invoice_id:
            return {'value': {
                'invoice_id': False,
                'base_amount': 0.0,
                'wh_src_rate': 0.0,
                'wh_amount': 0.0, }
            }

        inv_brw = inv_obj.browse(cr, uid, invoice_id)
        base_amount = base_amount or inv_brw.amount_untaxed
        wh_src_rate = wh_src_rate or inv_brw.wh_src_rate or 5.0
        wh_amount = base_amount * wh_src_rate / 100.0
        res = {'value': {
            'base_amount': base_amount,
            'wh_src_rate': wh_src_rate,
            'wh_amount': wh_amount,
        }
        }
        return res
    from bokeh.plotting import figure
    from bokeh.embed import components
    from bokeh.models import Legend, ColumnDataSource, LabelSet
except (ImportError, IOError) as err:
    _logger.debug(err)

OPERATORS = {
    '<': py_operator.lt,
    '>': py_operator.gt,
    '<=': py_operator.le,
    '>=': py_operator.ge,
    '==': py_operator.eq,
    '!=': py_operator.ne
}

UNIT = dp.get_precision('Product Unit of Measure')

_PRIORITY_LEVEL = [('1_red', 'Red'), ('2_yellow', 'Yellow'),
                   ('3_green', 'Green')]


class StockWarehouseOrderpoint(models.Model):
    _inherit = 'stock.warehouse.orderpoint'
    _description = "Stock Buffer"

    @api.multi
    @api.depends("dlt", "adu", "buffer_profile_id.lead_time_id.factor",
                 "buffer_profile_id.variability_id.factor",
                 "product_uom.rounding")
    def _compute_red_zone(self):
        for rec in self:
class AccountInvoiceCyC(models.Model):

    _name = 'account.invoice.cyc'
    _auto = False

    MONTHS = [(1, 'January'), (2, 'February'), (3, 'March'),
              (4, 'April'), (5, 'May'), (6, 'June'), (7, 'July'),
              (8, 'August'), (9, 'September'), (10, 'October'),
              (11, 'November'), (12, 'December')]

    country_id = fields.Many2one('res.country', 'Country', readonly=True)
    credit_covered = fields.Float('Credit covered', readonly=True,
                                  digits_compute=dp.get_precision('Account'))
    credit_not_covered = fields.Float(
        'Credit not covered', readonly=True,
        digits_compute=dp.get_precision('Account'))
    not_credit = fields.Float('No credit', readonly=True,
                              digits_compute=dp.get_precision('Account'))
    cash = fields.Float('Cash', readonly=True,
                        digits_compute=dp.get_precision('Account'))
    invoice_year = fields.Integer('Year', readonly=True)
    invoice_month = fields.Selection(MONTHS, string="Month", readonly=True)
    amount_total = fields.Float('Total', readonly=True,
                                digits_compute=dp.get_precision('Account'))
    invoice_state = fields.Selection([('open', 'Open'),('paid', 'Paid')],
                                     string="Invoice state", readonly=True)

    def init(self, cr):
        tools.drop_view_if_exists(cr, self._table)
        cr.execute("""CREATE VIEW account_invoice_cyc as (
select min(a.id) as id, a.country_id, sum(a.credit_covered) as credit_covered,
sum(a.credit_not_covered) as credit_not_covered,
sum(a.not_credit) as not_credit, sum(a.cash) as cash, a.invoice_year,
a.invoice_month, a.state as invoice_state, sum(a.credit_covered) +
sum(a.credit_not_covered)+ sum(a.not_credit) + sum(a.cash) as amount_total
from (select min(ai.id) as id, p.country_id,
SUM(ai.amount_total) as credit_covered,
0.0 as credit_not_covered, 0.0 as not_credit, 0.0 as cash,
extract(year from ai.date_invoice) as invoice_year,
extract(month from ai.date_invoice) as invoice_month, ai.state
from account_invoice ai inner join res_partner p on p.id = ai.partner_id
left join payment_mode pm on pm.id = ai.payment_mode_id
left join account_journal aj on aj.id = pm.journal
where p.credit_limit > 0 and p.risk_insurance_grant_date is not null and
(ai.payment_mode_id is null or aj.type != 'cash') and ai.type = 'out_invoice'
and ai.state in ('open', 'paid')
group by p.country_id, extract(year from ai.date_invoice),
extract(month from ai.date_invoice), ai.state
union
select min(ai.id) as id, p.country_id, -SUM(ai.amount_total) as credit_covered,
0.0 as credit_not_covered, 0.0 as not_credit, 0.0 as cash,
extract(year from ai.date_invoice) as invoice_year,
extract(month from ai.date_invoice) as invoice_month, ai.state
from account_invoice ai inner join res_partner p on p.id = ai.partner_id
left join payment_mode pm on pm.id = ai.payment_mode_id
left join account_journal aj on aj.id = pm.journal
where p.credit_limit > 0 and p.risk_insurance_grant_date is not null and
(ai.payment_mode_id is null or aj.type != 'cash') and ai.type = 'out_refund'
and ai.state in ('open', 'paid')
group by p.country_id, extract(year from ai.date_invoice),
extract(month from ai.date_invoice), ai.state
union
select min(ai.id) as id, p.country_id, 0.0 as credit_covered,
SUM(ai.amount_total) as credit_not_covered, 0.0 as not_credit, 0.0 as cash,
extract(year from ai.date_invoice) as invoice_year,
extract(month from ai.date_invoice) as invoice_month, ai.state
from account_invoice ai inner join res_partner p on p.id = ai.partner_id
left join payment_mode pm on pm.id = ai.payment_mode_id
left join account_journal aj on aj.id = pm.journal
where p.credit_limit > 0 and p.risk_insurance_grant_date is null and
(ai.payment_mode_id is null or aj.type != 'cash') and ai.type = 'out_invoice'
and ai.state in ('open', 'paid')
group by p.country_id, extract(year from ai.date_invoice),
extract(month from ai.date_invoice), ai.state
union
select min(ai.id) as id, p.country_id, 0.0 as credit_covered,
-SUM(ai.amount_total) as credit_not_covered, 0.0 as not_credit, 0.0 as cash,
extract(year from ai.date_invoice) as invoice_year,
extract(month from ai.date_invoice) as invoice_month, ai.state
from account_invoice ai inner join res_partner p on p.id = ai.partner_id
left join payment_mode pm on pm.id = ai.payment_mode_id
left join account_journal aj on aj.id = pm.journal
where p.credit_limit > 0 and p.risk_insurance_grant_date is null and
(ai.payment_mode_id is null or aj.type != 'cash') and ai.type = 'out_refund'
and ai.state in ('open', 'paid')
group by p.country_id, extract(year from ai.date_invoice),
extract(month from ai.date_invoice), ai.state
union
select min(ai.id) as id, p.country_id, 0.0 as credit_covered,
0.0 as credit_not_covered, SUM(ai.amount_total) as not_credit, 0.0 as cash,
extract(year from ai.date_invoice) as invoice_year,
extract(month from ai.date_invoice) as invoice_month, ai.state
from account_invoice ai inner join res_partner p on p.id = ai.partner_id
left join payment_mode pm on pm.id = ai.payment_mode_id
left join account_journal aj on aj.id = pm.journal
where p.credit_limit <= 0 and (ai.payment_mode_id is null or aj.type != 'cash')
and ai.type = 'out_invoice' and ai.state in ('open', 'paid')
group by p.country_id, extract(year from ai.date_invoice),
extract(month from ai.date_invoice), ai.state
union
select min(ai.id) as id, p.country_id, 0.0 as credit_covered,
0.0 as credit_not_covered, -SUM(ai.amount_total) as not_credit, 0.0 as cash,
extract(year from ai.date_invoice) as invoice_year,
extract(month from ai.date_invoice) as invoice_month, ai.state
from account_invoice ai inner join res_partner p on p.id = ai.partner_id
left join payment_mode pm on pm.id = ai.payment_mode_id
left join account_journal aj on aj.id = pm.journal
where p.credit_limit <= 0 and (ai.payment_mode_id is null or aj.type != 'cash')
and ai.type = 'out_refund' and ai.state in ('open', 'paid')
group by p.country_id, extract(year from ai.date_invoice),
extract(month from ai.date_invoice), ai.state
union
select min(ai.id) as id, p.country_id, 0.0 as credit_covered,
0.0 as credit_not_covered, 0.0 as not_credit, SUM(ai.amount_total) as cash,
extract(year from ai.date_invoice) as invoice_year,
extract(month from ai.date_invoice) as invoice_month, ai.state
from account_invoice ai inner join res_partner p on p.id = ai.partner_id
left join payment_mode pm on pm.id = ai.payment_mode_id
left join account_journal aj on aj.id = pm.journal
where aj.type = 'cash' and ai.type = 'out_invoice'
and ai.state in ('open', 'paid')
group by p.country_id, extract(year from ai.date_invoice),
extract(month from ai.date_invoice), ai.state
union
select min(ai.id) as id, p.country_id, 0.0 as credit_covered,
0.0 as credit_not_covered, 0.0 as not_credit, -SUM(ai.amount_total) as cash,
extract(year from ai.date_invoice) as invoice_year,
extract(month from ai.date_invoice) as invoice_month, ai.state
from account_invoice ai inner join res_partner p on p.id = ai.partner_id
left join payment_mode pm on pm.id = ai.payment_mode_id
left join account_journal aj on aj.id = pm.journal
where aj.type = 'cash' and ai.type = 'out_refund'
and ai.state in ('open', 'paid')
group by p.country_id, extract(year from ai.date_invoice),
extract(month from ai.date_invoice), ai.state) a
group by a.country_id, a.invoice_month, a.invoice_year, a.state)
""")
Beispiel #17
0
class kg_fettling_invoice(osv.osv):

    _name = "kg.fettling.invoice"
    _description = "Fettling Invoice"
    _order = "entry_date desc"

    def _amount_all(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        cur_obj = self.pool.get('res.currency')

        for order in self.browse(cr, uid, ids, context=context):

            res[order.id] = {
                'amount_untaxed': 0.0,
                'total_discount': 0.0,
                'amount_tax': 0.0,
                'total_amt': 0.0,
                'amount_total': 0.0,
                'payable_amt': 0.0,
                'additional_charges': 0.0,
                'advance_amt': 0.0,
            }
            tax_amt = discount_value = final_other_charges = advance_net_amt = 0.00
            total_value_amt = 0.00
            for line in order.line_ids:
                total_value_amt += line.total_value
            for item in order.line_ids_a:
                final_other_charges += item.expense_amt
            for line in order.line_ids_b:
                advance_net_amt += line.current_adv_amt
            if order.discount > 0:
                discount = order.discount
            else:
                discount = (total_value_amt * order.discount_per) / 100
            price_amt_val = total_value_amt - discount
            val = 0.00
            for c in self.pool.get('account.tax').compute_all(
                    cr, uid, order.tax_id, price_amt_val, 1, 1,
                    order.contractor_id)['taxes']:
                val += c.get('amount', 0.0)
                print "valvalval", val
                tax_amt = val

            if order.discount_per > 0.00:
                discount_value = (total_value_amt /
                                  100.00) * order.discount_per
            else:
                discount_value = order.discount

            res[order.id]['amount_untaxed'] = total_value_amt
            res[order.id]['total_discount'] = discount_value
            res[order.id]['amount_tax'] = tax_amt
            res[order.id]['additional_charges'] = final_other_charges
            res[order.id]['advance_amt'] = advance_net_amt
            res[order.id][
                'total_amt'] = final_other_charges + total_value_amt + tax_amt
            res[order.id]['amount_total'] = (
                final_other_charges + total_value_amt + tax_amt +
                order.round_off_amt) - (discount_value + advance_net_amt)
            res[order.id]['payable_amt'] = (
                final_other_charges + total_value_amt + tax_amt +
                order.round_off_amt) - (discount_value + advance_net_amt)
        return res

    _columns = {

        ## Version 0.1

        ## Basic Info
        'name':
        fields.char('Invoice No', size=24, select=True, readonly=True),
        'entry_date':
        fields.date('Invoice Date', required=True),
        'note':
        fields.text('Notes'),
        'state':
        fields.selection([('draft', 'Draft'), ('confirmed', 'Confirmed'),
                          ('cancel', 'Cancelled'),
                          ('approved', 'AC ACK Pending'),
                          ('done', 'AC ACK Done')],
                         'Status',
                         readonly=True),
        'entry_mode':
        fields.selection([('auto', 'Auto'), ('manual', 'Manual')],
                         'Entry Mode',
                         readonly=True),
        'flag_sms':
        fields.boolean('SMS Notification'),
        'flag_email':
        fields.boolean('Email Notification'),
        'flag_spl_approve':
        fields.boolean('Special Approval'),
        'narration':
        fields.char('Narration'),

        ### Entry Info ####
        'company_id':
        fields.many2one('res.company', 'Company Name', readonly=True),
        'active':
        fields.boolean('Active'),
        'crt_date':
        fields.datetime('Creation Date', readonly=True),
        'user_id':
        fields.many2one('res.users', 'Created By', readonly=True),
        'confirm_date':
        fields.datetime('Confirmed Date', readonly=True),
        'confirm_user_id':
        fields.many2one('res.users', 'Confirmed By', readonly=True),
        'ap_rej_date':
        fields.datetime('Approved Date', readonly=True),
        'done_date':
        fields.datetime('Done Date', readonly=True),
        'done_user_id':
        fields.many2one('res.users', 'Done By', readonly=True),
        'ap_rej_user_id':
        fields.many2one('res.users', 'Approved By', readonly=True),
        'cancel_date':
        fields.datetime('Cancelled Date', readonly=True),
        'cancel_user_id':
        fields.many2one('res.users', 'Cancelled By', readonly=True),
        'update_date':
        fields.datetime('Last Updated Date', readonly=True),
        'update_user_id':
        fields.many2one('res.users', 'Last Updated By', readonly=True),
        'cancel_remark':
        fields.text('Cancel'),
        'reject_remark':
        fields.text('Reject'),

        ## Module Requirement Info
        'contractor_id':
        fields.many2one(
            'res.partner',
            'Subcontractor',
            required=True,
            domain="[('contractor','=','t'),('partner_state','=','approve')]"),
        'phone':
        fields.char('Phone', size=64),
        'contact_person':
        fields.char('Contact Person', size=128),
        'inward_fettling_line_ids':
        fields.many2many(
            'ch.fettling.inward.line',
            'm2m_fettling_invoice_details',
            'order_id',
            'inward_id',
            'SC Items',
            domain=
            "[('flag_invoice','=',False),('contractor_id','=',contractor_id)]"
        ),
        'division_id':
        fields.many2one('kg.division.master',
                        'Division',
                        required=True,
                        domain="[('state','=','approved')]"),

        ## Calculation process Start now
        'con_invoice_no':
        fields.char('Contractor Invoice No', size=128, required=True),
        'invoice_date':
        fields.date('Contractor Invoice Date', required=True),
        'due_date':
        fields.date('Due Date', required=True),
        'invoice_amt':
        fields.float('Contractor Invoice Amount', required=True),
        'invoice_copy':
        fields.binary('Contractor Invoice Copy'),
        'filename':
        fields.char('File Name'),
        'tax_id':
        fields.many2many('account.tax', 'fettling_invoice_taxes', 'invoice_id',
                         'tax_id', 'Taxes'),
        'discount':
        fields.float('Discount Amount'),
        'discount_per':
        fields.float('Discount(%)'),
        'discount_flag':
        fields.boolean('Discount Flag'),
        'discount_per_flag':
        fields.boolean('Discount Amount Flag'),

        # Invoice Total and Tax amount calculation
        'amount_untaxed':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Untaxed Amount',
                        store=True,
                        multi="sums",
                        help="Untaxed Amount"),
        'total_discount':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Discount Amount(-)',
                        store=True,
                        multi="sums",
                        help="Discount Amount"),
        'amount_tax':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Tax Amount',
                        store=True,
                        multi="sums",
                        help="Tax Amount"),
        'total_amt':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Total Amount',
                        store=True,
                        multi="sums",
                        help="Total Amount"),
        'amount_total':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Net Amount',
                        store=True,
                        multi="sums",
                        help="Net Amount"),
        'payable_amt':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Payable Amount',
                        store=True,
                        multi="sums",
                        help="Payable Amount"),
        'additional_charges':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Additional Charges',
                        store=True,
                        multi="sums",
                        help="Additional Charges"),
        'advance_amt':
        fields.function(_amount_all,
                        digits_compute=dp.get_precision('Account'),
                        string='Adjected Advance Amount(-)',
                        multi="sums",
                        store=True,
                        readonly=True),
        'round_off_amt':
        fields.float('Round off(+/-)'),

        ##Accounts Process
        'balance_receivable':
        fields.float('Balance Receivable'),
        'accounts_state':
        fields.selection([('pending', 'Pending'), ('paid', 'Paid')],
                         'Accounts State',
                         readonly=True),
        ## Child Tables Declaration
        'line_ids':
        fields.one2many('ch.fettling.invoice.line', 'header_id',
                        "Line Details"),
        'line_ids_a':
        fields.one2many('ch.fettling.invoice.expense.track', 'header_id',
                        "Expense Track"),
        'line_ids_b':
        fields.one2many('ch.foundry.advance.details', 'header_id',
                        "Advance Details"),
    }

    _defaults = {
        'company_id':
        lambda self, cr, uid, c: self.pool.get('res.company').
        _company_default_get(cr, uid, 'kg_fettling_invoice', context=c),
        'entry_date':
        lambda *a: time.strftime('%Y-%m-%d'),
        'user_id':
        lambda obj, cr, uid, context: uid,
        'crt_date':
        lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
        'state':
        'draft',
        'active':
        True,
        'entry_mode':
        'manual',
        'accounts_state':
        'pending',
        'flag_sms':
        False,
        'flag_email':
        False,
        'flag_spl_approve':
        False,
        'discount_flag':
        False,
        'discount_per_flag':
        False,
    }

    def onchange_discount_value(self, cr, uid, ids, invoice_amt, discount_per):
        discount_value = invoice_amt * discount_per / 100.00
        if discount_per:
            return {'value': {'discount_flag': True}}
        else:
            return {'value': {'discount_flag': False}}

    def onchange_discount_percent(self, cr, uid, ids, invoice_amt, discount):
        if discount:
            discount = discount + 0.00
            amt_to_per = (discount / (invoice_amt or 1.0)) * 100.00
            return {'value': {'discount_per_flag': True}}
        else:
            return {'value': {'discount_per_flag': False}}

    def button_dummy(self, cr, uid, ids, context=None):
        return True

    def _future_entry_date_check(self, cr, uid, ids, context=None):
        rec = self.browse(cr, uid, ids[0])
        today = date.today()
        today = str(today)
        today = datetime.strptime(today, '%Y-%m-%d')
        entry_date = rec.entry_date
        entry_date = str(entry_date)
        entry_date = datetime.strptime(entry_date, '%Y-%m-%d')
        if entry_date > today or entry_date < today:
            return False
        return True

    _constraints = [

        #~ (_future_entry_date_check, 'System not allow to save with future and past date. !!',['Invoice Date']),
    ]

    def onchange_contractor(self, cr, uid, ids, contractor_id):
        value = {'contact_person': '', 'phone': ''}
        if contractor_id:
            contractor_rec = self.pool.get('res.partner').browse(
                cr, uid, contractor_id)
            value = {
                'contact_person': contractor_rec.contact_person,
                'phone': contractor_rec.phone
            }
        return {'value': value}

    def update_line_items(self, cr, uid, ids, context=None):
        entry = self.browse(cr, uid, ids[0])
        invoice_line_obj = self.pool.get('ch.fettling.invoice.line')

        del_sql = """ delete from ch_fettling_invoice_line where header_id=%s """ % (
            ids[0])
        cr.execute(del_sql)

        for item in entry.inward_fettling_line_ids:

            vals = {
                'header_id':
                entry.id,
                'fettling_id':
                item.fettling_id.id,
                'pattern_id':
                item.pattern_id.id,
                'pattern_code':
                item.pattern_code,
                'pattern_name':
                item.pattern_name,
                'moc_id':
                item.moc_id.id,
                'stage_id':
                item.stage_id.id,
                'stage_name':
                item.stage_name,
                'pour_id':
                item.pour_id.id,
                'pour_line_id':
                item.pour_line_id.id,
                'pump_model_id':
                item.pump_model_id.id,
                'order_bomline_id':
                item.order_bomline_id.id,
                'order_id':
                item.order_id.id,
                'order_line_id':
                item.order_line_id.id,
                'allocation_id':
                item.allocation_id.id,
                'schedule_id':
                item.schedule_id.id,
                'schedule_line_id':
                item.schedule_line_id.id,
                'qty':
                item.qty,
                'actual_qty':
                item.qty,
                'com_weight':
                item.each_weight,
                'seq_no':
                item.seq_no,
                'sub_inward_id':
                item.header_id.id,
                'sub_inward_line_id':
                item.id,
                'sub_wo_line_id':
                item.sub_wo_line_id.id,
                'com_moc_stage_id':
                [(6, 0, [x.id for x in item.com_moc_stage_id])],
            }

            invoice_line_id = invoice_line_obj.create(cr, uid, vals)

        return True

    def entry_confirm(self, cr, uid, ids, context=None):

        entry = self.browse(cr, uid, ids[0])
        final_other_charges = 0.00
        for item in entry.line_ids_a:
            final_other_charges += item.expense_amt
        ### Sequence Number Generation  ###
        if len(entry.line_ids) == 0:
            raise osv.except_osv(_('Invoice details is must !!'),
                                 _('Enter the proceed button!!'))
        if entry.state == 'draft':
            sc_inward_line_obj = self.pool.get('ch.fettling.inward.line')
            if (entry.invoice_amt + final_other_charges) > entry.amount_total:
                raise osv.except_osv(
                    _('Invoice Amount Exceed!!'),
                    _('System not allow to Invoice Amount grether than Net Amount !!'
                      ))
            if (entry.invoice_amt + final_other_charges) != entry.amount_total:
                raise osv.except_osv(
                    _('Invoice Amount !!'),
                    _('System allow to Invoice Amount is Equal to Net amount !!'
                      ))
            for line_item in entry.line_ids:
                if line_item.qty == 0:
                    raise osv.except_osv(
                        _('Warning!'),
                        _('System not allow to save Zero values !!'))

                sc_inward_line_obj.write(cr, uid,
                                         line_item.sub_inward_line_id.id, {
                                             'flag_invoice': True,
                                         })

            if entry.name == '' or entry.name == False:
                sc_invoice_name = ''
                sc_invoice_seq_id = self.pool.get('ir.sequence').search(
                    cr, uid, [('code', '=', 'kg.fettling.invoice')])
                rec = self.pool.get('ir.sequence').browse(
                    cr, uid, sc_invoice_seq_id[0])
                cr.execute("""select generatesequenceno(%s,'%s','%s') """ %
                           (sc_invoice_seq_id[0], rec.code, entry.entry_date))
                sc_invoice_name = cr.fetchone()
                sc_invoice_name = sc_invoice_name[0]
            else:
                sc_invoice_name = entry.name

            self.write(
                cr, uid, ids, {
                    'state': 'confirmed',
                    'name': sc_invoice_name,
                    'confirm_user_id': uid,
                    'confirm_date': time.strftime('%Y-%m-%d %H:%M:%S')
                })

        return True

    def entry_cancel(self, cr, uid, ids, context=None):
        rec = self.browse(cr, uid, ids[0])
        if rec.cancel_remark:
            self.write(
                cr, uid, ids, {
                    'state': 'cancel',
                    'cancel_user_id': uid,
                    'cancel_date': time.strftime('%Y-%m-%d %H:%M:%S')
                })
        else:
            raise osv.except_osv(
                _('Cancel remark is must !!'),
                _('Enter the remarks in Cancel remarks field !!'))
        return True

    def entry_reject(self, cr, uid, ids, context=None):
        rec = self.browse(cr, uid, ids[0])
        if rec.state == 'approved':
            if rec.reject_remark:
                self.write(
                    cr, uid, ids, {
                        'state': 'confirmed',
                        'update_user_id': uid,
                        'update_date': time.strftime('%Y-%m-%d %H:%M:%S')
                    })
            else:
                raise osv.except_osv(
                    _('Reject remark is must !!'),
                    _('Enter the remarks in Reject remarks field !!'))
            return True

    def entry_approved(self, cr, uid, ids, context=None):
        entry = self.browse(cr, uid, ids[0])
        final_other_charges = 0.00
        for item in entry.line_ids_a:
            final_other_charges += item.expense_amt
        if len(entry.line_ids) == 0:
            raise osv.except_osv(_('Invoice details is must !!'),
                                 _('Enter the proceed button!!'))
        if entry.state == 'confirmed':
            if (entry.invoice_amt + final_other_charges) > entry.amount_total:
                raise osv.except_osv(
                    _('Invoice Amount Exceed!!'),
                    _('System not allow to Invoice Amount grether than Net Amount !!'
                      ))
            if (entry.invoice_amt + final_other_charges) != entry.amount_total:
                raise osv.except_osv(
                    _('Invoice Amount !!'),
                    _('System allow to Invoice Amount is Equal to Net amount !!'
                      ))
            self.write(
                cr, uid, ids, {
                    'state': 'approved',
                    'ap_rej_user_id': uid,
                    'ap_rej_date': time.strftime('%Y-%m-%d %H:%M:%S')
                })
        else:
            pass
        return True

    def entry_accept(self, cr, uid, ids, context=None):
        rec = self.browse(cr, uid, ids[0])
        journal_obj = self.pool.get('account.journal')
        journal_ids = self.pool.get('account.journal').search(
            cr, uid, [('type', '=', 'purchase')])
        if journal_ids == []:
            raise osv.except_osv(
                _('Book Configuration Warning !!'),
                _('Type is purchase book should be created !!'))
        journal_rec = self.pool.get('account.journal').browse(
            cr, uid, journal_ids[0])
        if rec.state == 'approved':

            ## Advance code added start ##
            adjusted_amt = 0.00
            balance_amt = 0.00
            cus_adv_obj = self.pool.get('kg.subcontract.advance')
            cus_adv_inv_obj = self.pool.get('ch.foundry.advance.details')
            for line in rec.line_ids_b:
                print "line.order_id", line.order_id
                adv_ids = self.pool.get('kg.subcontract.advance').search(
                    cr, uid, [('fou_wo_id', '=', line.order_id.id)])
                print "adv_ids", adv_ids
                adv_rec = self.pool.get('kg.subcontract.advance').browse(
                    cr, uid, adv_ids[0])
                adjusted_amt = adv_rec.adjusted_amt + line.current_adv_amt
                balance_amt = line.current_adv_amt - adjusted_amt
                cus_adv_obj.write(cr, uid, line.sub_advance_id.id, {
                    'adjusted_amt': adjusted_amt,
                    'balance_amt': balance_amt
                })

            ## Advance code added end ##

            total_value_amt = 0.00
            for line in rec.line_ids:
                total_value_amt += line.total_value
            self.write(
                cr, uid, ids, {
                    'balance_receivable': rec.amount_total,
                    'state': 'done',
                    'done_user_id': uid,
                    'done_date': time.strftime('%Y-%m-%d %H:%M:%S')
                })

            ## Account Posting Process Start
            vou_obj = self.pool.get('account.voucher')
            move_vals = {
                'name': rec.name,
                'journal_id': journal_rec.id,
                'narration': rec.narration,
                'source_id': rec.id,
                'date': rec.entry_date,
                'division_id': rec.division_id.id,
                'trans_type': 'FI',
            }
            move_id = vou_obj.create_account_move(cr, uid, move_vals)
            if rec.contractor_id:
                account_id = rec.contractor_id.property_account_payable.id
                if not account_id:
                    raise osv.except_osv(
                        _('Contractor Configuration Warning !!'),
                        _('Contractor account should be configured !!'))
                credit = rec.amount_total
                debit = 0.00
                move_line_vals = {
                    'move_id': move_id,
                    'account_id': account_id,
                    'credit': credit,
                    'debit': debit,
                    'journal_id': journal_rec.id,
                    'date': rec.entry_date,
                    'name': rec.name,
                }
                move_line_id = vou_obj.create_account_move_line(
                    cr, uid, move_line_vals)

            for expense in rec.line_ids_a:
                ex_account_id = expense.expense.account_id.id
                if not ex_account_id:
                    raise osv.except_osv(
                        _('Expense Configuration Warning !!'),
                        _('Expense account should be configured !!'))
                move_line_vals = {
                    'move_id': move_id,
                    'account_id': ex_account_id,
                    'credit': 0.00,
                    'debit': expense.amount,
                    'journal_id': journal_rec.id,
                    'date': rec.entry_date,
                    'name': rec.name,
                }

                move_line_id = vou_obj.create_account_move_line(
                    cr, uid, move_line_vals)

            tax_sql = """ select sub_query.acc_col_id,sum(sub_query.debit) as debit
							from (
							select 
							ac_tax.account_collected_id as acc_col_id,
							sum((line_exp.amount * ac_tax.amount)) as debit
							from 
							fettling_invoice_expense_taxe line_tax 
							left join ch_fettling_invoice_expense_track line_exp on(line_exp.id=line_tax.invoice_id)
							left join account_tax ac_tax on(ac_tax.id=line_tax.tax_id)
							left join kg_fettling_invoice inv on(inv.id=line_exp.header_id)

							where line_exp.header_id = %s
							group by 1

							union all

							select 
							ac_tax.account_collected_id as acc_col_id,
							sum(((inv.amount_untaxed - inv.total_discount) * ac_tax.amount)) as debit
							from 
							fettling_invoice_taxes line_tax 

							left join kg_fettling_invoice inv on(inv.id=line_tax.invoice_id)
							left join account_tax ac_tax on(ac_tax.id=line_tax.tax_id)			

							where inv.id = %s
							group by 1) as sub_query

							group by 1""" % (rec.id, rec.id)
            cr.execute(tax_sql)
            data = cr.dictfetchall()
            for vals in data:
                if vals['acc_col_id'] is None:
                    raise osv.except_osv(
                        _('Account Configuration Warning !!'),
                        _('Tax account should be configured !!'))
                move_line_vals = {
                    'move_id': move_id,
                    'account_id': vals['acc_col_id'],
                    'credit': 0.00,
                    'debit': vals['debit'],
                    'journal_id': journal_rec.id,
                    'date': rec.entry_date,
                    'name': rec.name,
                }
                move_line_id = vou_obj.create_account_move_line(
                    cr, uid, move_line_vals)

            discount = 0.00
            if rec.amount_untaxed > 0:
                discount = 0.00
                if rec.discount > 0:
                    discount = rec.discount
                else:
                    discount = (total_value_amt * rec.discount_per) / 100
                account_ids = self.pool.get('account.account').search(
                    cr, uid, [('code', '=', 'CON INV')])
                if account_ids == []:
                    raise osv.except_osv(
                        _('Account Configuration Warning !!'),
                        _('code name is CON INV account should be created !!'))
                account_rec = self.pool.get('account.account').browse(
                    cr, uid, account_ids[0])
                account_id = account_rec.id
                if not account_id:
                    raise osv.except_osv(
                        _('Invoice Configuration Warning !!'),
                        _('Invoice account should be configured !!'))
                credit = 0.00
                debit = (rec.amount_untaxed + rec.round_off_amt) - discount
                move_line_vals = {
                    'move_id': move_id,
                    'account_id': account_id,
                    'credit': credit,
                    'debit': debit,
                    'journal_id': journal_rec.id,
                    'date': rec.entry_date,
                    'name': rec.name,
                }

                move_line_id = vou_obj.create_account_move_line(
                    cr, uid, move_line_vals)

            return True
        else:
            pass

    def load_advance(self, cr, uid, ids, context=None):
        invoice_rec = self.browse(cr, uid, ids[0])
        cus_adv_obj = self.pool.get('kg.subcontract.advance')
        cus_inadv_obj = self.pool.get('ch.foundry.advance.details')
        del_sql = """delete from ch_foundry_advance_details where header_id=%s""" % (
            ids[0])
        cr.execute(del_sql)
        for item in [x.id for x in invoice_rec.inward_fettling_line_ids]:
            work_rec_obj = self.pool.get('ch.fettling.inward.line').browse(
                cr, uid, item)
            adv_search = self.pool.get('kg.subcontract.advance').search(
                cr, uid,
                [('fou_wo_id', '=', work_rec_obj.sub_wo_line_id.header_id.id)])
            cr.execute(
                """ select * from kg_subcontract_advance where fou_wo_id = %s and balance_amt > 0 and state='confirmed'"""
                % (work_rec_obj.sub_wo_line_id.header_id.id))
            adv_data = cr.dictfetchall()
            for adv in adv_data:
                print "adv['order_id']0", adv['fou_wo_id']
                cus_inadv_obj.create(
                    cr, uid, {
                        'order_id': adv['fou_wo_id'],
                        'sub_advance_id': adv['id'],
                        'sub_advance_date': adv['entry_date'],
                        'tot_advance_amt': adv['advance_amt'],
                        'balance_amt': adv['balance_amt'],
                        'current_adv_amt': 0.0,
                        'header_id': invoice_rec.id,
                    })

        return True

    def unlink(self, cr, uid, ids, context=None):
        unlink_ids = []
        for rec in self.browse(cr, uid, ids):
            if rec.state != 'draft':
                raise osv.except_osv(_('Warning!'),
                                     _('You can not delete this entry !!'))
            else:
                unlink_ids.append(rec.id)
        return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)

    def create(self, cr, uid, vals, context=None):
        return super(kg_fettling_invoice, self).create(cr,
                                                       uid,
                                                       vals,
                                                       context=context)

    def write(self, cr, uid, ids, vals, context=None):
        vals.update({
            'update_date': time.strftime('%Y-%m-%d %H:%M:%S'),
            'update_user_id': uid
        })
        return super(kg_fettling_invoice, self).write(cr, uid, ids, vals,
                                                      context)

    def send_to_dms(self, cr, uid, ids, context=None):
        rec = self.browse(cr, uid, ids[0])
        res_rec = self.pool.get('res.users').browse(cr, uid, uid)
        rec_user = str(res_rec.login)
        rec_pwd = str(res_rec.password)
        rec_code = str(rec.name)
        encoded_user = base64.b64encode(rec_user)
        encoded_pwd = base64.b64encode(rec_pwd)

        url = 'http://192.168.1.7/sam-dms/login.html?xmxyypzr=' + encoded_user + '&mxxrqx=' + encoded_pwd + '&fettling_invoice=' + rec_code

        return {
            'name': 'Go to website',
            'res_model': 'ir.actions.act_url',
            'type': 'ir.actions.act_url',
            'target': 'current',
            'url': url
        }

    _sql_constraints = [
        ('name', 'unique(name)', 'No must be Unique !!'),
    ]
Beispiel #18
0
class ProfitLossReport(models.TransientModel):
    _name = 'profit.loss.report'

    categ_id = fields.Many2one(
        comodel_name='product.category',
        string='Product Category',
        readonly=True,
    )
    categ_name = fields.Char(
        string='Brand',
        readonly=True,
    )
    product_id = fields.Many2one(
        comodel_name='product.product',
        string='Referece',
        readonly=True,
    )
    lot_id = fields.Many2one(
        comodel_name='stock.production.lot',
        string='Case No.',
        readonly=True,
    )
    date_order = fields.Date(
        string='Date Registered',
        readonly=True,
    )
    user_id = fields.Many2one(
        comodel_name='res.users',
        string='Salesperson',
        readonly=True,
    )
    sale_order_id = fields.Many2one(
        comodel_name='sale.order',
        string='Quotation',
        readonly=True,
    )
    invoice_id = fields.Many2one(
        comodel_name='account.invoice',
        string='Invoice',
        readonly=True,
    )
    list_price = fields.Float(
        string='HK Retail',
        digits=dp.get_precision('Product Price'),
        readonly=True,
    )
    discount = fields.Float(
        string="Discount (%)",
        digits=dp.get_precision('Discount'),
        compute='_get_discount',
        readonly=True,
    )
    net_price = fields.Float(
        string="Net Price",
        digits=dp.get_precision('Product Price'),
        readonly=True,
    )
    net_price_currency_id = fields.Many2one(
        comodel_name='res.currency',
        string='Net Price Currency',
        readonly=True,
    )
    partner_id = fields.Many2one(
        comodel_name='res.partner',
        string='Customer',
        readonly=True,
    )
    partner_ref = fields.Char(
        string='Customer Ref.',
        readonly=True,
    )
    sale_order_note = fields.Text(
        string='Quotation Notes',
        readonly=True,
    )
    # FIXME we may deprecate this field if not needed
    sale_state = fields.Selection(
        [('open', 'Open Payment'), ('balance', 'Balance Payment'),
         ('done', 'Done')],
        string='Sales Status',
        readonly=True,
    )
    state = fields.Selection(
        [('purch_done', 'PO Done'), ('sale_done', 'SO Done'),
         ('sale_purch_done', 'SO and PO Done'),
         ('out_refund', 'Customer Refund'), ('in_refund', 'Supplier Refund')],
        string='Status',
        readonly=True,
    )
    out_move_id = fields.Many2one(
        comodel_name='stock.move',
        string='Outgoing Move',
        readonly=True,
    )
    out_move_date = fields.Date(
        string='Outgoing Move Date',
        readonly=True,
    )
    in_move_id = fields.Many2one(
        comodel_name='stock.move',
        string='Incoming Move',
        readonly=True,
    )
    in_move_date = fields.Date(
        string='Incoming Move Date',
        readonly=True,
    )
    in_period_id = fields.Many2one(
        comodel_name='account.period',
        string='Period',
        readonly=True,
    )
    in_move_quant_owner_id = fields.Many2one(
        comodel_name='res.partner',
        string='Owner',
        readonly=True,
    )
    stock_type = fields.Selection(
        [('own', 'Own Stock'), ('vci', 'VCI')],
        string='Stock Type',
        readonly=True,
    )
    purchase_order_id = fields.Many2one(
        comodel_name='purchase.order',
        string='Purchase Order',
        readonly=True,
    )
    supplier_id = fields.Many2one(
        comodel_name='res.partner',
        string='Supplier',
        readonly=True,
    )
    supplier_ref = fields.Char(
        string='Supplier Ref.',
        readonly=True,
    )
    purchase_currency_id = fields.Many2one(
        comodel_name='res.currency',
        string='Purchase Currency',
        readonly=True,
    )
    purchase_currency_price = fields.Float(
        string="Purchase Curr. Price",
        digits=dp.get_precision('Product Price'),
        readonly=True,
    )
    exchange_rate = fields.Float(
        digits=(12, 6),
        string='FX Rate',
        readonly=True,
    )
    purchase_base_price = fields.Float(
        string='Purchase Base Price',
        digits=dp.get_precision('Account'),
        readonly=True,
    )
    purchase_invoice_id = fields.Many2one(
        comodel_name='account.invoice',
        string='Purchase Invoice',
        readonly=True,
    )
    purchase_invoice_line_id = fields.Many2one(
        comodel_name='account.invoice.line',
        string='Purchase Invoice Line',
        readonly=True,
    )
    supplier_invoice_number = fields.Char(
        string='Supplier Invoice No.',
        readonly=True,
    )
    base_profit = fields.Float(
        string='Base Profit',
        readonly=True,
    )
    base_profit_percent = fields.Float(
        string='Profit %',
        digits=dp.get_precision('Account'),
        readonly=True,
    )
    customer_payment_ids = fields.Many2many(
        string='Customer Payment',
        comodel_name='account.move.line',
        related='invoice_id.payment_ids',
        readonly=True,
    )
    supplier_payment_ids = fields.Many2many(
        string='Supplier Payment',
        comodel_name='account.move.line',
        related='purchase_invoice_id.payment_ids',
        readonly=True,
    )
    supplier_payment_dates = fields.Char(
        string='Payment Date',
        readonly=True,
    )
    supplier_payment_ref = fields.Char(
        string='Payment Ref.',
        readonly=True,
    )
    supplier_payment_state = fields.Selection(
        [('to_pay', 'To Be Paid'), ('done', 'Done')],
        string='Supplier Payment Status',
        readonly=True,
    )
    customer_invoice_type = fields.Selection(
        [('out_invoice', 'Customer Invoice'),
         ('out_refund', 'Customer Refund')],
        readonly=True,
    )
    supplier_invoice_type = fields.Selection(
        [('in_invoice', 'Supplier Invoice'), ('in_refund', 'Supplier Refund')],
        readonly=True,
    )
    image_small = fields.Binary(
        'Image',
        related='product_id.product_tmpl_id.image_small',
        readonly=True,
    )
    customer_payment_information = fields.Char(
        string="Payment Information",
        readonly=True,
    )
    base_amount = fields.Float(
        string="Base Amount",
        digits=dp.get_precision('Product Price'),
        readonly=True,
    )

    @api.multi
    def _get_discount(self):
        for rec in self:
            if not rec.list_price or not rec.net_price:
                rec.discount = 0.0
            else:
                rec.discount = (1 - rec.net_price / rec.list_price) * 100
        return
Beispiel #19
0
class AccountInvoice(models.Model):

    _inherit = 'account.invoice'

    amount_retention = fields.Float(
        string='Retention',
        digits=dp.get_precision('Account'),
        readonly=True,
        states={'draft': [('readonly', False)]},
    )
    retention_on_payment = fields.Boolean(
        string='Retention on Payment',
        compute='_compute_retention_on_payment',
        store=True,
        help="If checked, retention will done during payment",
    )
    move_ids = fields.One2many(
        'account.move.line',
        related='move_id.line_id',
        string='Journal Items',
        readonly=True,
    )
    date_paid = fields.Date(
        string='Paid Date',
        compute='_compute_date_paid',
        store=True,
    )

    @api.multi
    @api.depends('state')
    def _compute_date_paid(self):
        for rec in self:
            if rec.state == 'paid' and rec.payment_ids:
                rec.date_paid = max(rec.payment_ids.mapped('date'))
            elif rec.state == 'open':
                rec.date_paid = False

    @api.multi
    @api.depends('invoice_line.price_subtotal',
                 'tax_line.amount',
                 'amount_retention')
    def _compute_amount(self):
        super(AccountInvoice, self)._compute_amount()
        for rec in self:
            rec.amount_tax = sum(line.amount for line in rec.tax_line)
            amount_total = rec.amount_untaxed + rec.amount_tax
            if not rec.retention_on_payment:
                rec.amount_total = amount_total - rec.amount_retention  # RET
            else:
                rec.amount_total = amount_total

    @api.multi
    @api.depends('partner_id')
    def _compute_retention_on_payment(self):
        for rec in self:
            rec.retention_on_payment = \
                self.env.user.company_id.retention_on_payment

    @api.multi
    def invoice_pay_customer(self):
        res = super(AccountInvoice, self).invoice_pay_customer()
        if res:
            res['context']['default_amount'] = 0.0
        return res
    #//////////////////////////////////////////////////////////////////////////////////////////////////
    @api.constrains('date_due','date_invoice')
    def date_compare(self):
        if self.type == 'in_invoice' and self.date_due != False:
            if self.date_due < self.date_invoice:
                raise ValidationError('Due Date is greater than or equal to Posting date')
# You should have received a copy of the GNU Affero General Public License     #
# along with this program.  If not, see <http://www.gnu.org/licenses/>.        #
###############################################################################

import time

from openerp.osv import orm, fields
from openerp.addons import decimal_precision as dp
from .res_company import COMPANY_FISCAL_TYPE, COMPANY_FISCAL_TYPE_DEFAULT

FISCAL_RULE_COLUMNS = {
    "partner_fiscal_type_id": fields.many2one("l10n_br_account.partner.fiscal.type", "Tipo Fiscal do Parceiro"),
    "fiscal_category_id": fields.many2one("l10n_br_account.fiscal.category", "Categoria"),
    "fiscal_type": fields.selection(COMPANY_FISCAL_TYPE, u"Regime Tributário", required=True),
    "revenue_start": fields.float(
        "Faturamento Inicial", digits_compute=dp.get_precision("Account"), help="Faixa inicial de faturamento bruto"
    ),
    "revenue_end": fields.float(
        "Faturamento Final", digits_compute=dp.get_precision("Account"), help="Faixa inicial de faturamento bruto"
    ),
}

OTHERS_FISCAL_RULE_COLUMNS_TEMPLATE = {
    "parent_id": fields.many2one("account.fiscal.position.rule.template", "Regra Pai"),
    "child_ids": fields.one2many("account.fiscal.position.rule.template", "parent_id", "Regras Filhas"),
}

OTHERS_FISCAL_RULE_COLUMNS = {
    "parent_id": fields.many2one("account.fiscal.position.rule", "Regra Pai"),
    "child_ids": fields.one2many("account.fiscal.position.rule", "parent_id", "Regras Filhas"),
}
class account_move_line(osv.osv):
    _inherit = "account.move.line"

    def _curr_debit_credit(self, cr, uid, ids, field_names, args, context=None):
        res = {}
        if context is None:
            context = {}
        currency_obj = self.pool.get('res.currency')
        alt_curr_ids = currency_obj.search(cr, uid, [('alt_currency','=',True)])
        alt_curr_id = alt_curr_ids and alt_curr_ids[0] or False
        ctx = context.copy()
        for move_line in self.browse(cr, uid, ids, context=context):
            res[move_line.id] = {
                'curr_debit': 0.0,
                'curr_credit': 0.0,
            }
            if alt_curr_id:
                ml_currency_id = move_line.currency_id and move_line.currency_id.id or False
                if ml_currency_id==alt_curr_id:
                    res[move_line.id].update({
                        'curr_debit': move_line.debit > 0 and abs(move_line.amount_currency) or 0.0,
                        'curr_credit': move_line.credit > 0 and abs(move_line.amount_currency) or 0.0,
                    })
                else:
                    ctx['date'] = move_line.date
                    res[move_line.id].update({
                        'curr_debit': currency_obj.compute(cr, uid, move_line.company_id.currency_id.id, alt_curr_id, move_line.debit, round=False, context=ctx),
                        'curr_credit': currency_obj.compute(cr, uid, move_line.company_id.currency_id.id, alt_curr_id, move_line.credit, round=False, context=ctx),
                    })
        return res

    @api.one
    @api.depends('currency_id')
    def _transaction_currency(self):
        if self.currency_id:
            self.transaction_curr_id = self.currency_id.id
        else:
            self.transaction_curr_id = self.company_id.currency_id.id

    _columns = {
        'curr_debit': fields.function(_curr_debit_credit, type="float", digits_compute=dp.get_precision('Account'), string='Debit %s', multi='debit_credit', help="Debit in Secundary Currency",
                                    store = { 'account.move.line': (lambda self, cr, uid, ids, c=None: ids, ['debit', 'currency_id', 'amount_currency'], 20),
                                              'res.currency': (lambda self, cr, uid, ids, c=None: self.pool['account.move.line'].search(cr, uid, []), ['alt_currency'], 20), }),
        'curr_credit': fields.function(_curr_debit_credit, type="float", digits_compute=dp.get_precision('Account'), string='Credit %s', multi='debit_credit', help="Credit in Secundary Currency",
                                    store = { 'account.move.line': (lambda self, cr, uid, ids, c=None: ids, ['credit', 'currency_id', 'amount_currency'], 20),
                                              'res.currency': (lambda self, cr, uid, ids, c=None: self.pool['account.move.line'].search(cr, uid, []), ['alt_currency'], 20), }),
        'transaction_curr_id': fields.many2one('res.currency', 'Transaction currency', compute="_transaction_currency", readonly=True, help="Currency of this transaction."),
    }

    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
        if context is None:
            context = {}
        res = super(account_move_line, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
        currency_obj = self.pool.get('res.currency')
        alt_curr_ids = currency_obj.search(cr, uid, [('alt_currency','=',True)])
        alt_curr_id = alt_curr_ids and alt_curr_ids[0] or False
        if alt_curr_id:
            alt_curr_name = currency_obj.read(cr, uid, alt_curr_id, ['name'], context=context)['name']
        precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
        for field in res['fields']:
            if alt_curr_id and field.startswith('curr_'):
                res['fields'][field]['string'] = res['fields'][field]['string'].replace('%s', alt_curr_name)
            if field == 'initial_bal':
                res['fields'][field]['digits'] = (16, precision)
            if field == 'curr_initial_bal':
                res['fields'][field]['digits'] = (16, precision)
        if not context.get('show_curr_debit_credit', False):
            res['fields'].pop('curr_debit', None)
            res['fields'].pop('curr_credit', None)
            doc = etree.XML(res['arch'])
            for node in doc.xpath("//field[@name='curr_debit']"):
                node.getparent().remove(node)
            for node in doc.xpath("//field[@name='curr_credit']"):
                node.getparent().remove(node)
            res['arch'] = etree.tostring(doc)
        return res

    def open_account_move(self, cr, uid, ids, context=None):
        context = context or {}
        row = self.browse(cr, uid, ids, context=context)[0]
        return {
                'type' : 'ir.actions.act_window',
                'name' :  _('Journal Entry'),
                'res_model': 'account.move',
                'view_type': 'form',
                'view_mode': 'form',
                'target': 'current',
                'res_id': row.move_id.id,
                'context': str(context)
        }

    def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True):
        context = context or {}
        res = super(account_move_line, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby, lazy=lazy)
        if context.get('include_initial_bal', False) and ('initial_bal' in fields or 'curr_initial_bal' in fields):
            precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
            for line in res:
                lines = self.search(cr, uid, line.get('__domain', domain), context=context)
                lines_rec = self.browse(cr, uid, lines, context=context)
                if 'initial_bal' in fields:
                    line['initial_bal'] = sum(line_rec.initial_bal for line_rec in lines_rec)
                    line['initial_bal'] = float_round(line['initial_bal'], precision_digits=precision)
                if 'curr_initial_bal' in fields:
                    line['curr_initial_bal'] = sum(line_rec.curr_initial_bal for line_rec in lines_rec)
                    line['curr_initial_bal'] = float_round(line['curr_initial_bal'], precision_digits=precision)
        return res
Beispiel #22
0
    def _onchange_partner(self):
        if self.partner_id:
            self.delivery_id = self.partner_id  # MAJ d'un autre champ
            # M2M : 2 possibilités :
            # - liste d'IDs, mais ça va AJOUTER les ids, comme (4, [IDs])
            # - [(6, 0, [IDs])], ce qui va remplacer les ids
            # (cf module product_category_tax dans akretion/odoo-usability)
            # On utilise un autre M2M pour le mettre à jour, on peut faire
            # self.champ_M2M_ids.ids -> ça donne la liste des IDs
            # M2O : recordset (ou ID)
            # O2M : ??
            # là, Odoo va jouer automatiquement le @api.onchange du champ delivery_id
            # pas besoin d'appeler le onchange de delivery_id dans notre code
        # Here, all form values are set on self
        # assigned values are not written to DB, but returned to the client
        # It is not possible to output a warning
        # It is not possible to put a raise UserError()
        # in this function (it will crash odoo)
        res = {'warning':
            {'title': _('Be careful'),
            {'message': _('here is the msg')}}
        # pour un domaine
        res = {'domain': {
            'champ1': "[('product_id', '=', product_id)]",
            'champ2': "[]"},
            }
        return res
        # si je n'ai ni warning ni domain, je n'ai pas besoin de faire un return

    # Fonction on_change déclarée dans la vue form/tree
    @api.multi
    def product_id_change(self, cr, uid, ids, champ1, champ2, context):
        # ATTENTION : a priori, on ne doit pas utiliser ids dans le code de la
        # fonction, car quand on fait un on_change avant le save, ids = []
        # Dans la vue XML :
        # <field name="product_id"
        #        on_change="product_id_change(champ1, champ2, context)" />
        # Piège : quand un champ float est passé dans un on_change,
        # si la personne avait tapé un entier, il va être passé en argument en
        # tant que integer et non en tant que float!

        raise orm.except_orm()
        # => il ne remet PAS l'ancienne valeur qui a déclanché le on_change

        # Pour mettre à jour des valeurs :
        return {'value': {'champ1': updated_value1, 'champ2': updated_value2}}
        # => à savoir : les onchange de 'champ1' et 'champ2' sont joués à
        # leur tour car leur valeur a été changée
        # si ces nouveaux on_change changent le product_id,
        # le product_id_change ne sera pas rejoué

        # Pour mettre un domaine :
        return {'domain': {
            'champ1': "[('product_id', '=', product_id)]",
            'champ2': "[]"},
            }
        # l'intégralité du domaine est dans une string

        # Pour retourner un message de warning :
        return {'warning': {
            'title': _('Le titre du msg de warn'),
            'message': _("Ce que j'ai à te dire %s") % (text)}}
        # Pour ne rien faire
        return False  # return True, ça marche en 7.0 mais ça bug en 6.1

    # La fonction de calcul du champ function price_subtotal
    @api.one  # auto-loop decorator
    @api.depends('price_unit', 'discount', 'invoice_line_tax_id', 'quantity',
        'product_id', 'invoice_id.partner_id', 'invoice_id.currency_id')
    # @api.depends est utilisé pour: invalidation cache, recalcul, onchange
    # donc, maintenant, le fait d'avoir un champ calculé fait qu'il est
    # automatiquement mis à jour dans la vue quand un de ses champs 'depends'
    # est modifié ! COOOOOL !
    # ATTENTION : si chgt de @api.depends, faire -u module !
    # Pour un one2many : ne PAS juste indiquer le nom du champ o2m, sinon il ne fait rien
    # il faut aussi indiquer un champ sur le O2M. Exemple : 'line_ids.request_id'
    # Apparemment, on peut mettre dans @api.depends un champ fonction stocké et ça va bien
    # faire le recalcul en cascade
    # (ça n'a pas l'air de marcher qd on met un api.depends sur un champ non stocké)
    def _compute_price(self):
        price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
        taxes = self.invoice_line_tax_id.compute_all(price, self.quantity, product=self.product_id, partner=self.invoice_id.partner_id)
        self.price_subtotal = taxes['total']  # calcul et stockage de la valeur
        self.second_field = 'iuit'  # calcul et stockage d'un 2e champ
                                    # equivalent de multi='pouet'
        # Pour un champ O2M, envoyer un recordset multiple ou une liste d'IDS
        # pour un champ M2O, donner le recordset ou l'ID
        if self.invoice_id:
            self.price_subtotal = self.invoice_id.currency_id.round(self.price_subtotal)
        # Pas besoin de return !
        # on ne peut PAS faire un self.write({}) dans la fonction de calcul d'un champ fonction

    # Pour un champ fonction, on peut aussi faire @api.multi:
    # untaxed = fields.Float(compute='_amounts')
    # taxes = fields.Float(compute='_amounts')
    # total = fields.Float(compute='_amounts')
    @api.multi
    @api.depends('lines.amount', 'lines.taxes')
    def _amounts(self):
        for order in self:
            order.untaxed = sum(line.amount for line in order.lines)
            order.taxes = sum(line.taxes for line in order.lines)
            order.total = order.untaxed + order + taxes

    # Champ fonction inverse='_inverse_price'
    @api.one
    def _inverse_loud(self):
        self.name = (self.loud or '').lower()  # MAJ du ou des autres champs

    # Champ fonction search='_search_price'
    def _search_loud(self, operator, value):
        if value is not False:
            value = value.lower()
        today = fields.Date.context_today(self)
        self._cr.execute('SELECT id FROM [cur_obj] WHERE (fortress_type <> %s OR (fortress_type = %s AND effectivity_date is not null)) AND (end_date is null OR end_date > %s)', (today, ))
        res_ids = [x[0] for x in self._cr.fetchall()]
        res = [('id', 'in', res_ids)] # recherche sur les autres champs
        return res

    # Fonction default=_default_account
    @api.model
    def _default_account(self):
        return valeur_par_defaut
        # M2O : retourne un recordset (ne PAS retourner False !)
        # O2M : retourne une liste de dict contenant la valeur des champs
        # date : string ou objet datetime

    # Fonction pour fields.selection
    @api.model
    def _type_list_get(self):
        return [('key1', _('String1')), ('key2', _('String2'))]

    ### CHAMPS
    # id, create_uid, write_uid, create_date et write_date
    # sont déjà utilisable dans le code python sans re-définition
    active = fields.Boolean(default=True)
    # Par défaut, string = nom du champ avec majuscule pour chaque début de mot
    login = fields.Char(
        string='Login', size=16, translate=True, required=True,
        help="My help message")
    display_name = fields.Char(
        string='Display Name', compute='_compute_display_name',
        readonly=True, store=True)
    comment = fields.Text(string='Comment', translate=True)
    html = fields.Html(string='report', translate=True)
    code_digits = fields.Integer(
        string='# of Digits', track_visibility='always', default=12,
        groups='base.group_user')
    # OU groups=['base.group_user', 'base.group_hr_manager']
    # groups = XMLID : restriction du read/write et invisible ds les vues
    sequence = fields.Integer(default=10)
    # track_visibility = always ou onchange
    amount_untaxed = fields.Float(
        'Amount untaxed', digits=dp.get_precision('Account'))
    # digits=(precision, scale)
    # Scale est le nombre de chiffres après la virgule
    # quand le float est un fields.float ou un fields.function,
    # on met l'option : digits=dp.get_precision('Account')
    # Autres valeurs possibles pour get_precision : product/product_data.xml
    # Product Price, Discount, Stock Weight, Product Unit of Measure,
    # Product UoS
    # fields.Monetary is only in version >= 9.0
    debit = fields.Monetary(default=0.0, currency_field='company_currency_id')
    start_date = fields.Date(
        string='Start Date', copy=False, default=fields.Date.context_today)
    # similaire : fields.Datetime and fields.Time
    type = fields.Selection([
        ('import', 'Import'),
        ('export', 'Export'),
        ], string="Type",
        default=lambda self: self._context.get('type', 'export'))
    # FIELDS.SELECTION ac selection dynamique :
    # type = fields.Selection('_type_list_get', string='Type', help='Pouet'),
    # Plus besoin de la double fonction pour que la 2e soit héritable
    # Pour ajouter des champs à un fields.Selection existant:
    # fields.Selection(
    #    selection_add=[('new_key1', 'My new key1'), ('new_key2', 'My New Key2')])
    picture = fields.Binary(string='Picture')
    # Pour fields.binary, il existe une option filters='*.png, *.gif',
    # qui restreint les formats de fichiers sélectionnables dans
    # la boite de dialogue, mais ça ne marche pas en GTK (on
    # ne peut rien sélectionner) et c'est pas supporté en Web, cf
    # https://bugs.launchpad.net/openobject-server/+bug/1076895
    picture_filename = fields.Char(string='Filename')
    # Les champs "picture" et "picture_filename" sont liés ensemble dans la vue
    # via la balise filename="picture_filename" sur le champ 'picture'
    # Il faut que le champ 'picture_filename' soit présent dans la vue
    # (il peut être invisible)
    # Pour un fichier à télécharger d'Odoo, le nom du fichier aura la valeur de
    # picture_filename
    # Pour un fichier à uploader dans Odoo, 'picture_filename' vaudra le nom
    # du fichier uploadé par l'utilisateur

    # Exemple de champ fonction stocké
    price_subtotal = fields.Float(
        string='Amount', digits= dp.get_precision('Account'),
        store=True, readonly=True, compute='_compute_price')
    # Exemple de champ function non stocké
    loud = fields.Char(
        store=False, compute='_compute_loud', inverse='_inverse_loud',
        search='_search_loud')
    account_id = fields.Many2one('account.account', string='Account',
        required=True, domain=[('type', 'not in', ['view', 'closed'])],
        default=_default_account)
    company_id = fields.Many2one(
        'res.company', string='Company',
        ondelete='cascade', required=True,
        default=lambda self: self.env['res.company']._company_default_get(
            'product.code'))
        # si on veut que tous les args soient nommés : comodel_name='res.company'
    user_id = fields.Many2one(
        'res.users', string='Salesman', default=lambda self: self.env.user)
    # ATTENTION : si j'ai déjà un domaine sur la vue,
    # c'est le domaine sur la vue qui prime !
    # ondelete='cascade' :
    # le fait de supprimer la company va supprimer l'objet courant !
    # ondelete='set null' (default)
    # si on supprime la company, le champ company_id est mis à 0
    # ondelete='restrict' :
    # si on supprime la company, ça déclanche une erreur d'intégrité !

    # Champ Relation
    company_currency_id = fields.Many2one(
        'res.currency', string='Currency', related='company_id.currency_id',
        store=True)
    # ATTENTION, en nouvelle API, on ne peut PAS faire un fields.Char qui
    # soit un related d'un fields.Selection (bloque le démarrage d'Odoo
    # sans message d'erreur !)

    line_ids = fields.One2many(
        'product.code.line', 'parent_id', string='Product lines',
        states={'done': [('readonly', True)]}, copy=True)
        # OU comodel_name='product.code.line', inverse_name='parent_id'
    # 2e arg = nom du champ sur l'objet destination qui est le M20 inverse
    # en v8 :
    # copy=True pour que les lignes soient copiées lors d'un duplicate
    # sinon, mettre copy=False (ça ne peut être qu'un booléen)
    # Valeur par défaut du paramètre "copy": True for normal fields, False for
    # one2many and computed fields, including property fields and related fields
    # ATTENTION : pour que states={} marche sur le champ A et que le
    # champ A est dans la vue tree, alors il faut que le champ "state"
    # soit aussi dans la vue tree.

    partner_ids = fields.Many2many(
        'res.partner', 'product_code_partner_rel', 'code_id', 'partner_id',
        'Related Partners')
    # 2e arg = nom de la table relation
    # 3e arg ou id1 = nom de la colonne dans la table relation
    # pour stocker l'ID du product.code
    # 4e arg ou id2 = nom de la colonne dans la table relation
    # pour stocker l'ID du res.partner
    # OU
    partner_ids = fields.Many2many(
        'res.partner', column1='code_id', column2='partner_id',
        string='Related Partners')
    # OU
    partner_ids = fields.Many2many(
        'res.partner', string='Related Partners')
    # Pour les 2 dernières définitions du M2M, il ne faut pas avoir
    # plusieurs champs M2M qui pointent du même obj vers le même obj

    # Champ property: il suffit de définit le champ comme un champ normal
    # et d'ajouter un argument company_dependent=True
    # Quand on veut lire la valeur d'un champ property dans une société
    # qui n'est pas celle de l'utilisateur, il faut passer dans le context
    # 'force_company': 8  (8 = ID de la company)
    }
Beispiel #23
0
class LunchOrderLine(models.Model):
    _name = 'lunch.order.line'
    _description = 'lunch order line'

    name = fields.Char(related='product_id.name', readonly=True)
    order_id = fields.Many2one('lunch.order',
                               'Order',
                               ondelete='cascade',
                               required=True)
    product_id = fields.Many2one('lunch.product', 'Product', required=True)
    category_id = fields.Many2one('lunch.product.category',
                                  string='Product Category',
                                  related='product_id.category_id',
                                  readonly=True,
                                  store=True)
    date = fields.Date(string='Date',
                       related='order_id.date',
                       readonly=True,
                       store=True)
    supplier = fields.Many2one('res.partner',
                               string='Vendor',
                               related='product_id.supplier',
                               readonly=True,
                               store=True)
    user_id = fields.Many2one('res.users',
                              string='User',
                              related='order_id.user_id',
                              readonly=True,
                              store=True)
    note = fields.Text('Note')
    price = fields.Float(related='product_id.price',
                         readonly=True,
                         store=True,
                         digits=dp.get_precision('Account'))
    state = fields.Selection([('new', 'New'), ('confirmed', 'Received'),
                              ('ordered', 'Ordered'),
                              ('cancelled', 'Cancelled')],
                             'Status',
                             readonly=True,
                             index=True,
                             default='new')
    cashmove = fields.One2many('lunch.cashmove', 'order_id', 'Cash Move')
    currency_id = fields.Many2one('res.currency',
                                  related='order_id.currency_id')

    @api.one
    def order(self):
        """
        The order_line is ordered to the vendor but isn't received yet
        """
        self.state = 'ordered'

    @api.one
    def confirm(self):
        """
        confirm one or more order line, update order status and create new cashmove
        """
        if self.state != 'confirmed':
            values = {
                'user_id': self.user_id.id,
                'amount': -self.price,
                'description': self.product_id.name,
                'order_id': self.id,
                'state': 'order',
                'date': self.date,
            }
            self.env['lunch.cashmove'].create(values)
            self.state = 'confirmed'

    @api.one
    def cancel(self):
        """
        cancel one or more order.line, update order status and unlink existing cashmoves
        """
        self.state = 'cancelled'
        self.cashmove.unlink()
                cr, uid, line.taxes_id, line.price, line.qty, line.product_id, line.back_order_id.partner_id
            )
            cur = line.back_order_id.pricelist_id.currency_id
            res[line.id] = cur_obj.round(cr, uid, cur, taxes["total"])
        return res

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

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

    _defaults = {"product_uom": _get_uom_id}


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class MailTrackingEmail(models.Model):
    _name = "mail.tracking.email"
    _order = 'time desc'
    _rec_name = 'display_name'
    _description = 'MailTracking email'

    name = fields.Char(string="Subject", readonly=True, index=True)
    display_name = fields.Char(string="Display name",
                               readonly=True,
                               store=True,
                               compute="_compute_display_name")
    timestamp = fields.Float(string='UTC timestamp',
                             readonly=True,
                             digits=dp.get_precision('MailTracking Timestamp'))
    time = fields.Datetime(string="Time", readonly=True)
    date = fields.Date(string="Date",
                       readonly=True,
                       compute="_compute_date",
                       store=True)
    mail_message_id = fields.Many2one(string="Message",
                                      comodel_name='mail.message',
                                      readonly=True)
    mail_id = fields.Many2one(string="Email",
                              comodel_name='mail.mail',
                              readonly=True)
    partner_id = fields.Many2one(string="Partner",
                                 comodel_name='res.partner',
                                 readonly=True)
    recipient = fields.Char(string='Recipient email', readonly=True)
    recipient_address = fields.Char(string='Recipient email address',
                                    readonly=True,
                                    store=True,
                                    compute='_compute_recipient_address')
    sender = fields.Char(string='Sender email', readonly=True)
    state = fields.Selection(
        [
            ('error', 'Error'),
            ('deferred', 'Deferred'),
            ('sent', 'Sent'),
            ('delivered', 'Delivered'),
            ('opened', 'Opened'),
            ('rejected', 'Rejected'),
            ('spam', 'Spam'),
            ('unsub', 'Unsubscribed'),
            ('bounced', 'Bounced'),
            ('soft-bounced', 'Soft bounced'),
        ],
        string='State',
        index=True,
        readonly=True,
        default=False,
        help=" * The 'Error' status indicates that there was an error "
        "when trying to sent the email, for example, "
        "'No valid recipient'\n"
        " * The 'Sent' status indicates that message was succesfully "
        "sent via outgoing email server (SMTP).\n"
        " * The 'Delivered' status indicates that message was "
        "succesfully delivered to recipient Mail Exchange (MX) server.\n"
        " * The 'Opened' status indicates that message was opened or "
        "clicked by recipient.\n"
        " * The 'Rejected' status indicates that recipient email "
        "address is blacklisted by outgoing email server (SMTP). "
        "It is recomended to delete this email address.\n"
        " * The 'Spam' status indicates that outgoing email "
        "server (SMTP) consider this message as spam.\n"
        " * The 'Unsubscribed' status indicates that recipient has "
        "requested to be unsubscribed from this message.\n"
        " * The 'Bounced' status indicates that message was bounced "
        "by recipient Mail Exchange (MX) server.\n"
        " * The 'Soft bounced' status indicates that message was soft "
        "bounced by recipient Mail Exchange (MX) server.\n")
    error_smtp_server = fields.Char(string='Error SMTP server', readonly=True)
    error_type = fields.Char(string='Error type', readonly=True)
    error_description = fields.Char(string='Error description', readonly=True)
    bounce_type = fields.Char(string='Bounce type', readonly=True)
    bounce_description = fields.Char(string='Bounce description',
                                     readonly=True)
    tracking_event_ids = fields.One2many(string="Tracking events",
                                         comodel_name='mail.tracking.event',
                                         inverse_name='tracking_email_id',
                                         readonly=True)

    @api.model
    def tracking_ids_recalculate(self,
                                 model,
                                 email_field,
                                 tracking_field,
                                 email,
                                 new_tracking=None):
        objects = self.env[model].search([
            (email_field, '=ilike', email),
        ])
        for obj in objects:
            trackings = obj[tracking_field]
            if new_tracking:
                trackings |= new_tracking
            trackings = trackings._email_score_tracking_filter()
            if set(obj[tracking_field].ids) != set(trackings.ids):
                if trackings:
                    obj.write({tracking_field: [(6, False, trackings.ids)]})
                else:
                    obj.write({tracking_field: [(5, False, False)]})
        return objects

    @api.model
    def _tracking_ids_to_write(self, email):
        trackings = self.env['mail.tracking.email'].search([
            ('recipient_address', '=ilike', email)
        ])
        trackings = trackings._email_score_tracking_filter()
        if trackings:
            return [(6, False, trackings.ids)]
        else:
            return [(5, False, False)]

    @api.multi
    def _email_score_tracking_filter(self):
        """Default email score filter for tracking emails"""
        # Consider only last 10 tracking emails
        return self.sorted(key=lambda r: r.time, reverse=True)[:10]

    @api.model
    def email_score_from_email(self, email):
        trackings = self.env['mail.tracking.email'].search([
            ('recipient_address', '=ilike', email)
        ])
        return trackings.email_score()

    @api.multi
    def email_score(self):
        """Default email score algorimth"""
        score = 50.0
        trackings = self._email_score_tracking_filter()
        for tracking in trackings:
            if tracking.state in ('error', ):
                score -= 50.0
            elif tracking.state in ('rejected', 'spam', 'bounced'):
                score -= 25.0
            elif tracking.state in ('soft-bounced', 'unsub'):
                score -= 10.0
            elif tracking.state in ('delivered', ):
                score += 5.0
            elif tracking.state in ('opened', ):
                score += 10.0
        if score > 100.0:
            score = 100.0
        return score

    @api.multi
    @api.depends('recipient')
    def _compute_recipient_address(self):
        for email in self:
            matches = re.search(r'<(.*@.*)>', email.recipient)
            if matches:
                email.recipient_address = matches.group(1)
            else:
                email.recipient_address = email.recipient

    @api.multi
    @api.depends('name', 'recipient')
    def _compute_display_name(self):
        for email in self:
            parts = [email.name]
            if email.recipient:
                parts.append(email.recipient)
            email.display_name = ' - '.join(parts)

    @api.multi
    @api.depends('time')
    def _compute_date(self):
        for email in self:
            email.date = fields.Date.to_string(
                fields.Date.from_string(email.time))

    @api.model
    def create(self, vals):
        tracking = super(MailTrackingEmail, self).create(vals)
        self.tracking_ids_recalculate('res.partner',
                                      'email',
                                      'tracking_email_ids',
                                      tracking.recipient_address,
                                      new_tracking=tracking)
        return tracking

    def _get_mail_tracking_img(self):
        base_url = self.env['ir.config_parameter'].get_param('web.base.url')
        path_url = (
            'mail/tracking/open/%(db)s/%(tracking_email_id)s/blank.gif' % {
                'db': self.env.cr.dbname,
                'tracking_email_id': self.id,
            })
        track_url = urlparse.urljoin(base_url, path_url)
        return ('<img src="%(url)s" alt="" '
                'data-odoo-tracking-email="%(tracking_email_id)s"/>' % {
                    'url': track_url,
                    'tracking_email_id': self.id,
                })

    @api.multi
    def smtp_error(self, mail_server, smtp_server, exception):
        self.sudo().write({
            'error_smtp_server': tools.ustr(smtp_server),
            'error_type': exception.__class__.__name__,
            'error_description': tools.ustr(exception),
            'state': 'error',
        })
        return True

    @api.multi
    def tracking_img_add(self, email):
        self.ensure_one()
        tracking_url = self._get_mail_tracking_img()
        if tracking_url:
            body = tools.append_content_to_html(email.get('body', ''),
                                                tracking_url,
                                                plaintext=False,
                                                container_tag='div')
            email['body'] = body
        return email

    def _message_partners_check(self, message, message_id):
        mail_message = self.mail_message_id
        partners = mail_message.notified_partner_ids | mail_message.partner_ids
        if (self.partner_id and self.partner_id not in partners):
            # If mail_message haven't tracking partner, then
            # add it in order to see his trackking status in chatter
            if mail_message.subtype_id:
                mail_message.sudo().write({
                    'notified_partner_ids': [(4, self.partner_id.id)],
                })
            else:
                mail_message.sudo().write({
                    'partner_ids': [(4, self.partner_id.id)],
                })
        return True

    @api.multi
    def _tracking_sent_prepare(self, mail_server, smtp_server, message,
                               message_id):
        self.ensure_one()
        ts = time.time()
        dt = datetime.utcfromtimestamp(ts)
        self._message_partners_check(message, message_id)
        self.sudo().write({'state': 'sent'})
        return {
            'recipient': message['To'],
            'timestamp': '%.6f' % ts,
            'time': fields.Datetime.to_string(dt),
            'tracking_email_id': self.id,
            'event_type': 'sent',
            'smtp_server': smtp_server,
        }

    def _event_prepare(self, event_type, metadata):
        self.ensure_one()
        m_event = self.env['mail.tracking.event']
        method = getattr(m_event, 'process_' + event_type, None)
        if method and hasattr(method, '__call__'):
            return method(self, metadata)
        else:  # pragma: no cover
            _logger.info('Unknown event type: %s' % event_type)
        return False

    def _concurrent_events(self, event_type, metadata):
        m_event = self.env['mail.tracking.event']
        self.ensure_one()
        concurrent_event_ids = False
        if event_type in {'open', 'click'}:
            ts = metadata.get('timestamp', time.time())
            delta = EVENT_OPEN_DELTA if event_type == 'open' \
                else EVENT_CLICK_DELTA
            domain = [
                ('timestamp', '>=', ts - delta),
                ('timestamp', '<=', ts + delta),
                ('tracking_email_id', '=', self.id),
                ('event_type', '=', event_type),
            ]
            if event_type == 'click':
                domain.append(('url', '=', metadata.get('url', False)))
            concurrent_event_ids = m_event.search(domain)
        return concurrent_event_ids

    @api.multi
    def event_create(self, event_type, metadata):
        event_ids = self.env['mail.tracking.event']
        for tracking_email in self:
            other_ids = tracking_email._concurrent_events(event_type, metadata)
            if not other_ids:
                vals = tracking_email._event_prepare(event_type, metadata)
                if vals:
                    event_ids += event_ids.sudo().create(vals)
                partners = self.tracking_ids_recalculate(
                    'res.partner', 'email', 'tracking_email_ids',
                    tracking_email.recipient_address)
                if partners:
                    partners.email_score_calculate()
            else:
                _logger.debug("Concurrent event '%s' discarded", event_type)
        return event_ids

    @api.model
    def event_process(self, request, post, metadata, event_type=None):
        # Generic event process hook, inherit it and
        # - return 'OK' if processed
        # - return 'NONE' if this request is not for you
        # - return 'ERROR' if any error
        return 'NONE'  # pragma: no cover
Beispiel #26
0
class ProcurementOrderQuantity(models.Model):
    _inherit = 'procurement.order'

    move_dest_id = fields.Many2one('stock.move', index=True)
    product_id = fields.Many2one('product.product', index=True)
    state = fields.Selection(index=True)
    qty = fields.Float(
        string="Quantity",
        digits_compute=dp.get_precision('Product Unit of Measure'),
        help='Quantity in the default UoM of the product',
        compute="_compute_qty",
        store=True)

    @api.multi
    @api.depends('product_qty', 'product_uom')
    def _compute_qty(self):
        for m in self:
            qty = self.env['product.uom']._compute_qty_obj(
                m.product_uom, m.product_qty, m.product_id.uom_id)
            m.qty = qty

    @api.model
    def _procure_orderpoint_confirm(self,
                                    use_new_cursor=False,
                                    company_id=False,
                                    run_procurements=True,
                                    run_moves=True):
        """
        Create procurement based on orderpoint

        :param bool use_new_cursor: if set, use a dedicated cursor and auto-commit after processing each procurement.
            This is appropriate for batch jobs only.
        """
        orderpoint_env = self.env['stock.warehouse.orderpoint']
        dom = company_id and [('company_id', '=', company_id)] or []
        if self.env.context.get(
                'compute_product_ids'
        ) and not self.env.context.get('compute_all_products'):
            dom += [('product_id', 'in',
                     self.env.context.get('compute_product_ids'))]
        if self.env.context.get(
                'compute_supplier_ids'
        ) and not self.env.context.get('compute_all_products'):
            supplierinfo_ids = self.env['product.supplierinfo']. \
                search([('name', 'in', self.env.context['compute_supplier_ids'])])
            read_supplierinfos = supplierinfo_ids.read(
                ['id', 'product_tmpl_id'], load=False)
            dom += [('product_id.product_tmpl_id', 'in',
                     [item['product_tmpl_id'] for item in read_supplierinfos])]
        orderpoints = orderpoint_env.search(dom)
        if run_procurements:
            self.env['procurement.order'].run_confirm_procurements(
                company_id=company_id)
        if run_moves:
            domain = company_id and [('company_id', '=', company_id)] or False
            self.env['procurement.order'].run_confirm_moves(domain)
        last_date_done = dt.now() - relativedelta(months=1)
        last_date_done = fields.Datetime.to_string(last_date_done)
        self.env.cr.execute(
            """DELETE FROM stock_scheduler_controller WHERE done IS TRUE AND date_done < %s""",
            (last_date_done, ))
        self.env.cr.execute(
            """INSERT INTO stock_scheduler_controller
(orderpoint_id,
 product_id,
 location_id,
 location_sequence,
 route_sequence,
 run_procs,
 done,
 create_date,
 write_date,
 create_uid,
 write_uid)

  WITH user_id AS (SELECT %s AS user_id),

      orderpoints_to_insert AS (
        SELECT
          op.id                                     AS orderpoint_id,
          op.product_id,
          op.location_id,
          COALESCE(sl.stock_scheduler_sequence, 0)  AS location_sequence,
          COALESCE(slr.stock_scheduler_sequence, 0) AS route_sequence,
          FALSE                                     AS run_procs,
          FALSE                                     AS done,
          CURRENT_TIMESTAMP                         AS create_date,
          CURRENT_TIMESTAMP                         AS write_date,
          (SELECT user_id
           FROM user_id)                            AS create_uid,
          (SELECT user_id
           FROM user_id)                            AS write_uid
        FROM stock_warehouse_orderpoint op
          LEFT JOIN stock_location sl ON sl.id = op.location_id
          LEFT JOIN product_product pp ON pp.id = op.product_id
          LEFT JOIN stock_route_product rel ON rel.product_id = pp.product_tmpl_id
          LEFT JOIN stock_location_route slr ON slr.id = rel.route_id
        WHERE op.id IN %s
        GROUP BY op.id, sl.stock_scheduler_sequence, slr.stock_scheduler_sequence),

      list_sequences AS (
        SELECT
          location_sequence,
          route_sequence
        FROM orderpoints_to_insert
        GROUP BY location_sequence, route_sequence)

  SELECT *
  FROM orderpoints_to_insert

  UNION ALL

  SELECT
    NULL              AS orderpoint_id,
    NULL              AS product_id,
    NULL              AS location_id,
    location_sequence,
    route_sequence,
    TRUE              AS run_procs,
    FALSE             AS done,
    CURRENT_TIMESTAMP AS create_date,
    CURRENT_TIMESTAMP AS write_date,
    (SELECT user_id
     FROM user_id)    AS create_uid,
    (SELECT user_id
     FROM user_id)    AS write_uid
  FROM list_sequences""", (self.env.uid, tuple(orderpoints.ids + [0])))
        return {}

    @api.multi
    def cancel(self):
        result = super(ProcurementOrderQuantity, self).cancel()
        if self.env.context.get('unlink_all_chain'):
            delete_moves_cancelled_by_planned = bool(
                self.env['ir.config_parameter'].get_param(
                    'stock_procurement_just_in_time.delete_moves_cancelled_by_planned',
                    default=False))
            if delete_moves_cancelled_by_planned:
                moves_to_unlink = self.env['stock.move']
                procurements_to_unlink = self.env['procurement.order']
                for rec in self:
                    parent_moves = self.env['stock.move'].search([
                        ('procurement_id', '=', rec.id)
                    ])
                    for move in parent_moves:
                        if move.state == 'cancel':
                            moves_to_unlink += move
                            if procurements_to_unlink not in procurements_to_unlink and move.procurement_id and \
                                move.procurement_id.state == 'cancel' and \
                                    not any([move.state == 'done' for move in move.procurement_id.move_ids]):
                                procurements_to_unlink += move.procurement_id
                if moves_to_unlink:
                    moves_to_unlink.unlink()
                if procurements_to_unlink:
                    procurements_to_unlink.unlink()
        return result

    @api.model
    def propagate_cancel(self, procurement):
        """
        Improves the original propagate_cancel, in order to cancel it even if one of its moves is done.
        """
        ignore_move_ids = procurement.rule_id.action == 'move' and procurement.move_ids and \
            procurement.move_ids.filtered(lambda move: move.state == 'done').ids or []
        if procurement.rule_id.action == 'move':
            # Keep proc with new qty if some moves are already done
            procurement.remove_done_moves()
        return super(
            ProcurementOrderQuantity,
            self.sudo().with_context(
                ignore_move_ids=ignore_move_ids)).propagate_cancel(procurement)

    @api.model
    def remove_done_moves(self):
        """Splits the given procs creating a copy with the qty of their done moves and set to done.
        """
        for procurement in self:
            if procurement.rule_id.action == 'move':
                qty_done = sum([
                    move.product_qty for move in procurement.move_ids
                    if move.state == 'done'
                ])
                qty_done_proc_uom = self.env['product.uom']. \
                    _compute_qty_obj(procurement.product_id.uom_id, qty_done, procurement.product_uom)
                if procurement.product_uos:
                    qty_done_proc_uos = float_round(
                        self.env['product.uom']._compute_qty_obj(
                            procurement.product_id.uom_id, qty_done,
                            procurement.product_uos),
                        precision_rounding=procurement.product_uos.rounding)
                else:
                    qty_done_proc_uos = float_round(
                        qty_done_proc_uom,
                        precision_rounding=procurement.product_uom.rounding)
                if float_compare(qty_done,
                                 0.0,
                                 precision_rounding=procurement.product_id.
                                 uom_id.rounding) > 0:
                    procurement.write({
                        'product_qty':
                        float_round(qty_done_proc_uom,
                                    precision_rounding=procurement.product_uom.
                                    rounding),
                        'product_uos_qty':
                        qty_done_proc_uos,
                    })
Beispiel #27
0
class account_invoice(osv.Model):
    _inherit = 'account.invoice'

    def get_discount_payment_invoice(self,
                                     cr,
                                     uid,
                                     invoice_id,
                                     date,
                                     context=None):
        """
            Obtiene el descuento que corresponde sobre la factura
        """
        disc_obj = self.pool.get('product.pricelist.discount')
        item_obj = self.pool.get('product.pricelist.discount.item')

        inv = self.browse(cr, uid, invoice_id, context=context)
        amount = inv.type in ('out_refund',
                              'in_refund') and -inv.residual or inv.residual

        # Obtiene el descuento que se debe aplicar por pronto pago
        discount = 0.0
        discount_amount = 0.0

        # Valida que la factura sea una factura de cliente y que tenga un precio de lista
        if inv.type == 'out_invoice' and inv.pricelist_id:
            # Obtiene los datos de la factura
            inv_date = inv.date_invoice
            pricelist = inv.pricelist_id.id

            # Obtiene los descuentos disponibles en donde se aplican pagos
            type_ids = self.pool.get('product.pricelist.discount.type').search(
                cr, uid, [('to_paid', '=', True)], context=context)

            # Obtiene el numero de dias en relacion al pago contra la factura
            days = disc_obj.get_number_days(
                cr, uid, inv_date, date, context=context) - 1

            # Valida si se debe aplicar un descuento sobre pronto pago
            discount_ids = disc_obj.search(cr, uid,
                                           [('type_id', 'in', type_ids),
                                            ('pricelist_id', '=', pricelist)])
            if discount_ids:
                # Recorre los descuentos sobre pagos y valida si se aplican en alguna de las reglas
                for disc in disc_obj.browse(cr,
                                            uid,
                                            discount_ids,
                                            context=context):
                    # Valida que el descuento tenga un codigo
                    if not disc.type_id.key:
                        continue

                    # Recorre las reglas aplicadas sobre el descuento
                    for item in disc.item_ids:
                        apply_discount = False

                        # Valida si hay categorias que excluyen el descuento
                        if item_obj.validate_exception_categ(cr,
                                                             uid,
                                                             item.id,
                                                             inv.id,
                                                             context=context):
                            continue

                        # Valida que los dias de la factura al pago correspondan al descuento
                        if item.min_quantity >= days:
                            discount += item.discount
                            break

            # Si el descuento es mayor a cero obtiene el valor de la factura
            if discount > 0.0:
                # Obtiene el monto del descuento
                discount_amount = (inv.amount_total -
                                   inv.discount_sale) * (discount / 100)
                # Trunca el descuento a dos digitos
                discount_amount = float(int(discount_amount * 100.0)) / 100.0
                amount += inv.type in (
                    'out_refund',
                    'in_refund') and discount_amount or -discount_amount
        return discount_amount, amount

    def generate_voucher_invoice(self,
                                 cr,
                                 uid,
                                 invoice_id,
                                 refund_id,
                                 context=None):
        """
            Genera el cobro automatico de una factura sobre una nota de credito
        """
        inv_obj = self.pool.get('account.invoice')
        v_obj = self.pool.get('account.voucher')
        v_line_obj = self.pool.get('account.voucher.line')
        move_line_obj = self.pool.get('account.move.line')
        journal_pool = self.pool.get('account.journal')
        total_credit = 0.0
        total_debit = 0.0
        account_type = 'receivable'
        type_line = 'receipt'

        # Obtiene la informacion de la factura
        inv = inv_obj.browse(cr, uid, invoice_id, context=context)

        if inv.type in ['in_invoice', 'in_refund']:
            account_type = 'payable'
            type_line = 'payment'
        else:
            account_type = 'receivable'
            type_line = 'receipt'

        reconcile = 0
        to_reconcile_ids = []
        # Recorre las lineas de la factura y obtiene los movimientos a pagar de la factura
        movelines = inv.move_id.line_id
        for line in movelines:
            # Si la factura origen ya esta pagada en su totalidad se omite el proceso
            if (line.account_id.id == inv.account_id.id) and (type(
                    line.reconcile_id) == osv.orm.browse_null):
                to_reconcile_ids.append(line.id)
                reconcile += 1
                total_credit += line.credit or 0.0
                total_debit += line.debit or 0.0

        # Si no se encontraron lineas para conciliar termina el proceso
        if reconcile == 0:
            return True

        # Obtiene la informacion de la nota de credito
        refund = inv_obj.browse(cr, uid, refund_id, context=context)
        reconcile = 0
        # Recorre las lineas de la nota de credito y obtiene los movimientos a pagar de la factura
        movelines = refund.move_id.line_id
        for line in movelines:
            # Si la factura origen ya esta pagada en su totalidad se omite el proceso
            if (line.account_id.id == refund.account_id.id) and (type(
                    line.reconcile_id) == osv.orm.browse_null):
                to_reconcile_ids.append(line.id)
                reconcile += 1
                total_credit += line.credit or 0.0
                total_debit += line.debit or 0.0
        # Si no se encontraron lineas para conciliar termina el proceso
        if reconcile == 0:
            return True

        # Obtiene la cuenta que se va a aplicar para el voucher
        account_id = inv.partner_id.property_account_receivable.id

        line_cr_ids = []
        line_dr_ids = []
        voucher_line = []
        concilie = 0
        # Recorre las lineas de movimiento y crea las lineas del voucher
        for line in move_line_obj.browse(cr,
                                         uid,
                                         to_reconcile_ids,
                                         context=context):
            amount_unreconciled = abs(line.amount_residual_currency)
            reconcile = False
            if line.credit:
                amount = min(amount_unreconciled, abs(total_debit))
                total_debit -= amount
            else:
                amount = min(amount_unreconciled, abs(total_credit))
                total_credit -= amount
            line_type = line.credit and 'dr' or 'cr'

            # Revisa si se esta conciliando el movimiento completo
            if amount_unreconciled == amount and concilie == 0:
                reconcile = True
                if total_credit == 0 or total_debit == 0:
                    concilie = 1
            # Genera un arreglo con la informacion de la linea a generar
            rs = {
                'name': line.move_id.name,
                'type': line_type,
                'move_line_id': line.id,
                'account_id': line.account_id.id,
                'amount_original': abs(line.amount_currency),
                'amount': amount,
                'date_original': line.date,
                'date_due': line.date_maturity,
                'amount_unreconciled': amount_unreconciled,
                'currency_id': inv.currency_id.id,
                'reconcile': reconcile
            }

            # Agrega la informacion a los cargos o abonos
            if rs['type'] == 'cr':
                line_cr_ids.append(rs)
            else:
                line_dr_ids.append(rs)
            voucher_line.append(rs)

        writeoff_amount = v_obj._compute_writeoff_amount(
            cr, uid, line_dr_ids, line_cr_ids, 0.0, type_line)

        vals = {
            'invoice_id': inv.id,
            'partner_id': inv.partner_id.id,
            'currency_id': inv.currency_id.id,
            'type': type_line,
            'pre_line': 1,
            'writeoff_amount': writeoff_amount,
            'account_id': account_id
        }

        # Crea el nuevo voucher para la factura
        v_id = v_obj.create(cr, uid, vals)

        # Crea las lineas del voucher
        for line in voucher_line:
            line['voucher_id'] = v_id
            v_line_obj.create(cr, uid, line, context=context)

        # Aplica el pago sobre los movimientos
        wf_service = netsvc.LocalService("workflow")
        wf_service.trg_validate(uid, 'account.voucher', v_id,
                                'proforma_voucher', cr)
        return v_id

    def _create_refund_to_discount(self, cr, uid, invoice, context=None):
        """
            Crea la nota de credito donde se aplica el descuento comercial, volumen y mezcla
        """
        obj_journal = self.pool.get('account.journal')
        cur_obj = self.pool.get('res.currency')
        inv_obj = self.pool.get('account.invoice')
        inv_line_obj = self.pool.get('account.invoice.line')
        if context is None:
            context = {}
        type_dict = {
            'out_invoice': 'out_refund',  # Customer Invoice
            'in_invoice': 'in_refund',  # Supplier Invoice
            'out_refund': 'out_invoice',  # Customer Refund
            'in_refund': 'in_invoice',  # Supplier Refund
        }
        invoice_data = {}

        for field in [
                'name', 'reference', 'comment', 'date_due', 'partner_id',
                'company_id', 'account_id', 'currency_id', 'payment_term',
                'user_id', 'fiscal_position'
        ]:
            if invoice._all_columns[field].column._type == 'many2one':
                invoice_data[field] = invoice[field].id
            else:
                invoice_data[
                    field] = invoice[field] if invoice[field] else False
        tax_lines = filter(lambda l: l['manual'], invoice.tax_line)
        tax_lines = inv_obj._refund_cleanup_lines(cr,
                                                  uid,
                                                  tax_lines,
                                                  context=context)

        # Obtenemos el diario para la nota de debito
        refund_journal = invoice.journal_id.journal_refund_id
        # Valida que exista
        if not refund_journal:
            raise osv.except_osv(
                _('Error!'),
                _("Diario automatico para nota de debito, no configurado, configure el diario sobre diario de credito"
                  ))
        if refund_journal.type not in ('sale_refund', 'purchase_refund'):
            raise osv.except_osv(
                _('Error!'),
                _("Configurar el diario de nota de debito con: credito de compra o credito de venta"
                  ))

        date = time.strftime('%Y-%m-%d')
        invoice_data.update({
            'type': type_dict[invoice['type']],
            'date_invoice': date,
            'state': 'draft',
            'number': False,
            #'tax_line': tax_lines,
            'journal_id': refund_journal.id or False,
            'invoice_id': invoice.id
        })

        # Agrega el campo de tipo de nota de credito si lo trae entre los parametros
        if context.get('default_filter_refund', False):
            invoice_data['filter_refund'] = context.get(
                'default_filter_refund', False)

        invoice_id = inv_obj.create(cr, uid, invoice_data, context=context)
        cur = invoice.currency_id

        # Recorre las lineas de la factura
        for line in invoice.invoice_line:
            # Obtiene el monto del descuento de venta por la linea
            price = line.price_subtotal
            amount_discount = 0.0
            discount_sale = 0.0
            # Aplica al subtotal el descuento comercial y al impuesto
            if line.discount_com > 0:
                discount_sale = price * (line.discount_com / 100)
                price = price - discount_sale
                amount_discount += discount_sale
            # Aplica al subtotal el descuento de mezcla y al impuesto
            if line.discount_mez > 0:
                discount_sale = price * (line.discount_mez / 100)
                price = price - discount_sale
                amount_discount += discount_sale
            # Aplica al subtotal el descuento de volumen y al impuesto
            if line.discount_vol > 0:
                discount_sale = price * (line.discount_vol / 100)
                price = price - discount_sale
                amount_discount += discount_sale

            # Valida que el descuento no sea cero
            if amount_discount == 0.0:
                continue
            #tax = line.
            amount_discount = cur_obj.round(cr, uid, cur, amount_discount)
            vals = {
                'product_id':
                line.product_id.id or False,
                'name':
                'Descuento (Comercial: %s %%, Volumen: %s %%, Mezcla: %s %%) - %s '
                % (line.discount_com, line.discount_vol, line.discount_mez,
                   line.name),
                'quantity':
                1,
                'uos_id':
                line.uos_id.id,
                'price_unit':
                amount_discount,
                #'tax_line': tax_lines,
                'account_id':
                line.account_id.id or False,
                'invoice_line_tax_id':
                [(6, 0, [x.id for x in line.invoice_line_tax_id])],
                'invoice_id':
                invoice_id
            }
            #print "****************** vals despues de agregar tax de create refund *************",vals

            inv_line_obj.create(cr, uid, vals, context=context)

        # Actualiza los totales de la factura
        inv_obj.write(cr, uid, [invoice_id], {}, context=context)

        return invoice_id

    def invoice_validate(self, cr, uid, ids, context=None):
        """
            Si la factura tiene descuentos genera la nota de credito
        """
        wf_service = netsvc.LocalService('workflow')

        # Funcion original de validar factura
        res = super(account_invoice, self).invoice_validate(cr,
                                                            uid,
                                                            ids,
                                                            context=context)

        # Revisa si alguna factura es de nota de credito y ve si tiene que aplicar una modificacion sobre la factura origen
        for inv in self.browse(cr, uid, ids, context=context):
            if inv.amount_total == 0.0 and inv.type in [
                    'out_refund', 'in_refund'
            ]:
                raise osv.except_osv(
                    _('Error!'),
                    _("No puede validar notas de credito en cero: '%s'!") %
                    (inv.number, ))

            # Valida que sea una nota de credito generada para el cliente
            if inv.type in ['out_invoice']:
                # Valida si hay descuento sobre la factura
                if inv.discount_sale:
                    # Crea la nota de credito con la informacion del descuento financiero
                    refund_id = self._create_refund_to_discount(
                        cr, uid, inv, context=context)

                    # Pasa la factura a abierto
                    wf_service.trg_validate(uid, 'account.invoice', \
                                                 refund_id, 'invoice_open', cr)
                    # Salda la nota de credito con la factura
                    self.generate_voucher_invoice(cr,
                                                  uid,
                                                  inv.id,
                                                  refund_id,
                                                  context=context)

                    # Actualiza el total de descuento sobre la venta obtenido por la nota de credito
                    refund = self.browse(cr, uid, refund_id, context=context)
                    self.write(cr, uid, [inv.id],
                               {'discount_sale': refund.amount_total})
        return res

    def invoice_pay_customer(self, cr, uid, ids, context=None):
        """
            Abre el formulario para los cobros desde  la factura
        """
        if not ids: return []
        dummy, view_id = self.pool.get('ir.model.data').get_object_reference(
            cr, uid, 'account_voucher', 'view_vendor_receipt_dialog_form')
        date = time.strftime('%Y-%m-%d')

        inv = self.browse(cr, uid, ids[0], context=context)
        # Obtiene el descuento sobre la factura
        discount_amount, amount = self.get_discount_payment_invoice(
            cr, uid, inv.id, date, context=context)

        return {
            'name': _("Pay Invoice"),
            'view_mode': 'form',
            'view_id': view_id,
            'view_type': 'form',
            'res_model': 'account.voucher',
            'type': 'ir.actions.act_window',
            'nodestroy': True,
            'target': 'new',
            'domain': '[]',
            'context': {
                'payment_expected_currency':
                inv.currency_id.id,
                'default_partner_id':
                self.pool.get('res.partner')._find_accounting_partner(
                    inv.partner_id).id,
                'default_amount':
                amount,
                'default_discount':
                discount_amount,
                'default_invoice_amount':
                inv.residual,
                'default_reference':
                inv.name,
                'close_after_process':
                True,
                'invoice_type':
                inv.type,
                'invoice_id':
                inv.id,
                'default_type':
                inv.type in ('out_invoice', 'out_refund') and 'receipt'
                or 'payment',
                'type':
                inv.type in ('out_invoice', 'out_refund') and 'receipt'
                or 'payment'
            }
        }

    def onchange_partner_id(self,
                            cr,
                            uid,
                            ids,
                            type,
                            partner_id,
                            date_invoice=False,
                            payment_term=False,
                            partner_bank_id=False,
                            company_id=False):
        """
            Cuando se modifique el cliente tiene que actualizar el precio de lista que contenga
        """
        # Funcion original onchange
        res = super(account_invoice,
                    self).onchange_partner_id(cr, uid, ids, type, partner_id,
                                              date_invoice, payment_term,
                                              partner_bank_id, company_id)

        #~ # Si no esta el metodo de pago relacionado con el cliente pone el metodo de no identificado
        #~ if partner_id:
        #~ partner = self.pool.get('res.partner').browse(cr, uid, partner_id)
        #~ # Si el cliente tiene una lista de precio relacionada, actualiza el valor en la factura
        #~ if partner.property_product_pricelist:
        #~ res['value']['pricelist_id'] = partner.property_product_pricelist.id
        return res

    _columns = {
        'pricelist_id':
        fields.many2one('product.pricelist', 'Tarifa'),
        'discount_fin':
        fields.float('Descuento', digits_compute=dp.get_precision('Account')),
        'discount_sale':
        fields.float('Descuento', digits_compute=dp.get_precision('Account')),
        'tax_line':
        fields.one2many('account.invoice.tax',
                        'invoice_id',
                        'Tax Lines',
                        readonly=True,
                        states={'draft': [('readonly', False)]}),
    }
class proforma_invoice(osv.osv):
    def _amount_all(self, cr, uid, ids, name, args, context=None):
        res = {}
        tax_obj = self.pool.get('account.tax')
        for invoice in self.browse(cr, uid, ids, context=context):
            res[invoice.id] = {
                'amount_untaxed': 0.0,
                'amount_tax': 0.0,
                'amount_total': 0.0
            }
            for line in invoice.invoice_line:
                res[invoice.id]['amount_untaxed'] += line.price_subtotal
            for line in invoice.invoice_line:
                taxes = tax_obj.compute_all(cr,
                                            uid,
                                            line.invoice_line_tax_id,
                                            line.price_unit,
                                            line.quantity,
                                            product=line.product_id,
                                            partner=line.invoice_id.partner_id)
                res[invoice.id][
                    'amount_tax'] += taxes['total_included'] - taxes['total']
            res[invoice.id]['amount_total'] = res[
                invoice.id]['amount_tax'] + res[invoice.id]['amount_untaxed']
        return res

    def _get_sequence(self, cr, uid, ids, name, args, context=None):
        res = {}
        sale_obj = self.pool.get('sale.order')
        for invoice in self.browse(cr, uid, ids, context=context):
            seq = False
            if invoice.sale_id:
                curr_pi = invoice.sale_id.proforma_ids
                curr_seq_pi = [x.sequence for x in curr_pi]
                len_curr_seq = max(curr_seq_pi)
                if not invoice.sequence:
                    seq = len_curr_seq + 1

            if not invoice.sequence:
                res[invoice.id] = seq
            else:
                res[invoice.id] = invoice.sequence
        return res

    _name = "proforma.invoice"
    _description = 'Proforma Invoice'
    _order = "id desc"
    _columns = {
     'sequence' : fields.function(_get_sequence, type="integer", string='Sequence Number', store=True),
     'name': fields.char('Proforma Invoice', size=64, select=True, readonly=True),
     'sale_id' : fields.many2one('sale.order','Sales Contract'),
     # 'origin': fields.char('Source Document', size=64, help="Reference of the document that produced this proforma invoice."),
     'note': fields.text('Internal Information'),
     'type': fields.selection([
      ('out_invoice','Customer Invoice'),
      ('in_invoice','Supplier Invoice'),
      ],'Type', readonly=True, select=True, change_default=True, track_visibility='always'),
     # 'state': fields.selection([
     #	 ('draft','Draft'),
     #	 ('proforma','Pro-forma'),
     #	 ('cancel','Cancelled'),
     #	 ],'Status', select=True, readonly=True, track_visibility='onchange',
     #	 help=' * The \'Draft\' status is used when a user is encoding a new and unconfirmed Invoice. \
     #	 \n* The \'Pro-forma\' when invoice is in Pro-forma status,invoice does not have an invoice number. \
     #	 \n* The \'Cancelled\' status is used when user cancel invoice.'),
     'sent': fields.boolean('Sent', readonly=True, help="It indicates that the proforma invoice has been sent."),
     'date_invoice': fields.date('Invoice Date', readonly=False, select=True, help="Keep empty to use the current date"),
     # 'date_due': fields.date('Due Date', readonly=True, states={'draft':[('readonly',False)]}, select=True,
     #	 help="If you use payment terms, the due date will be computed automatically at the generation "\
     #		 "of accounting entries. The payment term may compute several due dates, for example 50% now and 50% in one month, but if you want to force a due date, make sure that the payment term is not set on the invoice. If you keep the payment term and the due date empty, it means direct payment."),
     'partner_id': fields.many2one('res.partner', 'Buyer', change_default=True, readonly=False, required=True, track_visibility='always'),
     'p_address_text' : fields.text('Buyer Address Custom'),
     'p_use_custom_address' : fields.boolean('Use Custom Buyer Address?'),
     'consignee_partner_id': fields.many2one('res.partner', 'Consignee', change_default=True, readonly=False, required=True, track_visibility='always'),
     'c_address_text' : fields.text('Consignee Address Custom'),
     'c_use_custom_address' : fields.boolean('Use Custom Consignee Address?'),
     'notify_partner_id': fields.many2one('res.partner', 'Notify', change_default=True, readonly=False, required=False, track_visibility='always'),
     'n_address_text' : fields.text('Notify Address Custom'),
     'n_use_custom_address' : fields.boolean('Use Custom Notify Address?'),
     'shipper_id': fields.many2one('res.partner', 'Shipper', change_default=True, readonly=False, required=True, track_visibility='always'),
     's_address_text' : fields.text('Shipper Address Custom'),
     's_use_custom_address' : fields.boolean('Use Custom Shipper Address?'),
     'payment_term': fields.many2one('account.payment.term', 'Payment Terms',readonly=False,
      help="If you use payment terms, the due date will be computed automatically at the generation "\
       "of accounting entries. If you keep the payment term and the due date empty, it means direct payment. "\
       "The payment term may compute several due dates, for example 50% now, 50% in one month."),
     # 'tax_line': fields.one2many('proforma.invoice.tax', 'invoice_id', 'Tax Lines', readonly=True, states={'draft':[('readonly',False)]}),
     'invoice_line': fields.one2many('proforma.invoice.line', 'invoice_id', 'Invoice Lines', readonly=False),
     'amount_untaxed': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Subtotal', track_visibility='always', multi='all'),
     'amount_tax': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Tax', multi='all'),
     'amount_total': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Total', multi='all'),
     'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=False, track_visibility='always'),
     'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=False),
     'remit_to' : fields.many2one('res.bank', 'Remit To',
      help=''),
     'credit_to' : fields.many2one('res.bank', 'Credit To',
      help=''),
     'company_bank_account' : fields.many2one('res.partner.bank', 'Bank Account',
      help='Bitratex Bank Account'),
     'user_id': fields.many2one('res.users', 'Salesperson', readonly=False, track_visibility='onchange'),
    }

    def _invoice_line_for(self, cr, uid, order_line):
        invoice_line = {
            'name': order_line.name,
            # 'origin': fields.char('Source Document', size=256, help="Reference of the document that produced this proforma invoice."),
            # 'sequence': fields.integer('Sequence', help="Gives the sequence of this line when displaying the invoice."),
            'uom_id': order_line.product_uom.id,
            'product_id': order_line.product_id.id,
            'price_unit': order_line.price_unit,
            'invoice_line_tax_id': [(6, 0, [x.id for x in order_line.tax_id])],
            'quantity': order_line.product_uom_qty,
        }
        if order_line.order_id.sale_type == 'export':
            invoice_line['name'] = order_line.export_desc
        return invoice_line

    def default_get(self, cr, uid, fields, context):
        if context is None: context = {}
        res = super(proforma_invoice, self).default_get(cr,
                                                        uid,
                                                        fields,
                                                        context=context)
        sale_id = context.get('sale_id', False)

        # active_model = context.get('active_model')
        # assert active_model in ('sale.order'), 'Bad context propagation'

        if sale_id:
            sale = self.pool.get('sale.order').browse(cr, uid, sale_id)

            if 'sale_id' in fields:
                res.update(sale_id=sale.id)
            if 'partner_id' in fields:
                res.update(partner_id=sale.partner_id.id)
            if 'consignee_partner_id' in fields:
                res.update(
                    consignee_partner_id=sale.consignee and sale.consignee.id
                    or sale.partner_invoice_id and sale.partner_invoice_id.id
                    or sale.partner_id.id)
            if 'notify_partner_id' in fields:
                res.update(
                    notify_partner_id=sale.notify and sale.notify.id or False)
            if 'payment_term' in fields:
                res.update(payment_term=False)
            if 'currency_id' in fields:
                res.update(
                    payment_term=sale.currency_id and sale.currency_id.id
                    or False)
            if 'company_id' in fields:
                res.update(
                    payment_term=sale.currency_id and sale.currency_id.id
                    or False)
            if 'date_invoice' in fields:
                res.update(date=time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
            # if 'opening_bank' in fields:
            # 	res.update(payment_term=sale.opening_bank and sale.opening_bank.id or False)
            # if 'intermed_bank' in fields:
            # 	res.update(payment_term=sale.intermed_bank and sale.intermed_bank.id or False)
            # if 'negotiate_bank' in fields:
            # 	res.update(payment_term=sale.negotiate_bank and sale.negotiate_bank.id or False)
            if 'invoice_line' in fields:
                line_ids = [
                    self._invoice_line_for(cr, uid, order_line)
                    for order_line in sale.order_line
                    if order_line.state not in ('done')
                ]
                res.update(invoice_line=line_ids)

        return res

    _defaults = {
        'type':
        'out_invoice',
        'date_invoice':
        lambda *a: time.strftime('%Y-%m-%d'),
        'currency_id':
        lambda self, cr, uid, context: self.pool.get('res.users').browse(
            cr, uid, uid, context).company_id.currency_id.id or False,
        'company_id':
        lambda self, cr, uid, c: self.pool.get('res.company').
        _company_default_get(cr, uid, 'account.invoice', context=c),
        'shipper_id':
        lambda self, cr, uid, c: self.pool.get('res.users').browse(
            cr, uid, uid, c).company_id.partner_id.id or False,
        'user_id':
        lambda s, cr, u, c: u,
        'sent':
        False,
    }

    def create(self, cr, uid, vals, context=None):
        res = super(proforma_invoice, self).create(cr,
                                                   uid,
                                                   vals,
                                                   context=context)
        pi_id = self.browse(cr, uid, res)
        if pi_id:
            company_code = ''

            if pi_id.company_id:
                company_code = pi_id.company_id.name[0:1]

            if pi_id.sale_id:
                if pi_id.sale_id.sale_type == 'export':
                    self.write(
                        cr, uid, res, {
                            'name':
                            (company_code + 'E ' +
                             (self.pool.get('ir.sequence').get(
                                 cr, uid, 'proforma.invoice.export') or '/'))
                        })
                elif pi_id.sale_id.sale_type == 'local':
                    self.write(
                        cr, uid, res, {
                            'name':
                            (company_code + 'L ' +
                             (self.pool.get('ir.sequence').get(
                                 cr, uid, 'proforma.invoice.local') or '/'))
                        })
            else:
                self.write(
                    cr, uid, res, {
                        'name': (company_code + ' ' +
                                 (self.pool.get('ir.sequence').get(
                                     cr, uid, 'proforma.invoice') or '/'))
                    })
        return res

    def get_address(self, partner_obj):
        if partner_obj:
            partner_address = ''
            partner_address += partner_obj.street and partner_obj.street + '\n ' or ''
            partner_address += partner_obj.street2 and partner_obj.street2 + '\n ' or ''
            partner_address += partner_obj.street3 and partner_obj.street3 + '\n ' or ''
            partner_address += partner_obj.city and partner_obj.city + ' ' or ''
            partner_address += partner_obj.zip and partner_obj.zip + ', ' or ''
            partner_address += partner_obj.country_id.name and partner_obj.country_id.name or ''

            return partner_address
        else:
            return False

    def onchange_check(self, cr, uid, ids, partner_id, context=None):
        if context is None:
            context = {}
        if not partner_id:
            return {'value': {}}

        result = {}
        partner = self.pool.get('res.partner').browse(cr, uid, partner_id)
        if context.get('shipper', False) and partner:
            result.update({'s_address_text': self.get_address(partner)})
        if context.get('consignee', False) and partner:
            result.update({'c_address_text': self.get_address(partner)})
        if context.get('partner', False) and partner:
            result.update({'p_address_text': self.get_address(partner)})
        if context.get('notify', False) and partner:
            result.update({'n_address_text': self.get_address(partner)})

        return {'value': result}
Beispiel #29
0
# -*- coding: utf-8 -*-

import logging
import time

from osv import osv, fields
import openerp.addons.decimal_precision as dp

DP = dp.get_precision('Budget')


class BudgetBudget(osv.osv):
    """
    Implementacion de clase de Presupuesto
    """
    _name = 'budget.budget'
    _order = 'code'

    _columns = {
        'code': fields.char('Código', size=64, required=True),
        'name': fields.char('Presupuesto', size=128, required=True),
        'department_id': fields.many2one('hr.department',
                                         string='Departamento',
                                         required=True),
        'date_start': fields.date('Fecha Inicio', required=True),
        'date_end': fields.date('Fecha Fin', required=True),
        'state': fields.selection(
            [('draft','Borrador'),
            ('open','Ejecución'),
            ('close','Cerrado')],
            string='Estado',
class AgreementLine(models.Model):
    _name = 'account.periodical_invoicing.agreement.line'
    _order = 'sequence, id'

    sequence = fields.Integer(default=10)
    active_chk = fields.Boolean(
        string='Active',
        default=True,
        help='Unchecking this field, this quota is not generated')
    agreement_id = fields.Many2one('account.periodical_invoicing.agreement',
                                   'Agreement reference',
                                   ondelete='cascade')
    product_id = fields.Many2one('product.product',
                                 'Product',
                                 ondelete='set null',
                                 required=True)
    name = fields.Char(related='product_id.name',
                       string='Description',
                       store=False)
    additional_description = fields.Text(
        string='Add. description',
        help='Additional description that will be added to the product '
        'description on invoices.')
    quantity = fields.Float(string='Quantity',
                            required=True,
                            default=1,
                            help='Quantity of the product to invoice')
    price = fields.Float(
        'Product price',
        digits_compute=dp.get_precision('Account'),
        help='Specific price for this product. Keep empty to use the '
        'current price while generating invoice')
    discount = fields.Float('Discount (%)', digits=(16, 2))
    invoicing_interval = fields.Integer(
        string='Interval',
        required=True,
        default=1,
        help="Interval in time units for invoicing this product")
    invoicing_unit = fields.Selection(selection=[('days', 'days'),
                                                 ('weeks', 'weeks'),
                                                 ('months', 'months'),
                                                 ('years', 'years')],
                                      string='Interval unit',
                                      required=True,
                                      default='months')
    last_invoice_date = fields.Date(string='Last invoice')

    _sql_constraints = [
        ('line_qty_zero', 'CHECK (quantity > 0)',
         'All product quantities must be greater than 0.\n'),
        ('line_interval_zero', 'CHECK (invoicing_interval > 0)',
         'All invoicing intervals must be greater than 0.\n'),
    ]

    def copy(self, cr, uid, orig_id, default=None, context=None):
        if default is None:
            default = {}
        default.update({
            'last_invoice_date': False,
        })
        return super(AgreementLine, self).copy(cr,
                                               uid,
                                               orig_id,
                                               default,
                                               context=context)

    def onchange_product_id(self,
                            cr,
                            uid,
                            ids,
                            product_id=False,
                            context=None):
        result = {}
        if product_id:
            product = self.pool['product.product'].browse(cr,
                                                          uid,
                                                          product_id,
                                                          context=context)
            if product:
                result['value'] = {'name': product['name']}
        return result
Beispiel #31
0
        'inv_company': fields.char('CompanyName', size=256, help='Only applicable when Sold to option is empty or not present.'),
        'inv_tax_id_no': fields.char('TaxIdentificationNumber', size=256, help='Only applicable when Sold to option is empty or not present.'),
        'inv_att_name': fields.char('AttentionName', size=256, help='Only applicable when Sold to option is empty or not present.'),
        'inv_address_id': fields.many2one('res.partner', 'Sold To Address', help='Only applicable when Sold to option is empty or not present.'),
        'blanket_begin_date': fields.date('Blanket Begin Date'),
        'blanket_end_date': fields.date('Blanket End Date'),
<<<<<<< HEAD
        'comm_code': fields.char('Commodity Code', size=256,),
=======
#        'comm_code': fields.char('Commodity Code', size=256,),
        'comm_code':fields.many2one('ups.commodity.code','Commodity Code'),
>>>>>>> c1979f64b3360c86d60e00c92be0271d89f97f2d

        'exp_carrier': fields.char('ExportingCarrier', size=256),
        'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64),
        'ship_charge': fields.float('Value', digits_compute=dp.get_precision('Account'))
    }

    _defaults = {
        'address_validate': 'nonvalidate',
        'comm_inv': False,
        'cer_orig': False,
        'nafta_cer_orig': False,
        'sed': False,
        'ship_state' : 'draft',
        'bill_shipping': 'shipper',
        'ship_charge': 0.0,
        'exp_carrier':"United Parcel Service"
    }
    
    
class productSimplePricelistItemUpdateWizard(TransientModel):
    _name = 'product.simple.pricelist.item.update.wizard'

    # Default Get Section
    def default_get(self, cr, uid, fields, context=None):
        pp_obj = self.pool['product.product']
        pplv_obj = self.pool['product.pricelist.version']
        res = super(productSimplePricelistItemUpdateWizard,
                    self).default_get(cr, uid, fields, context=context)
        pp = pp_obj.browse(cr, uid, context['product_id'], context=context)
        pplv = pplv_obj.browse(cr,
                               uid,
                               context['pricelist_version_id'],
                               context=context)

        res.update({
            'product_id': pp.id,
            'list_price': pp.list_price,
            'pricelist_id': pplv.pricelist_id.id,
            'pricelist_version_id': pplv.id,
        })
        return res

    # Column Section
    _columns = {
        'list_price':
        fields.float('List Price',
                     required=True,
                     readonly=True,
                     digits_compute=dp.get_precision('Product Price')),
        'pricelist_id':
        fields.many2one('product.pricelist',
                        'Pricelist',
                        required=True,
                        readonly=True),
        'pricelist_version_id':
        fields.many2one('product.pricelist.version',
                        'Pricelist Version',
                        required=True,
                        readonly=True),
        'product_id':
        fields.many2one('product.product',
                        'Product',
                        required=True,
                        readonly=True),
        'specific_price':
        fields.float('Price',
                     required=True,
                     digits_compute=dp.get_precision('Product Price')),
    }

    # Button Section
    def set_price(self, cr, uid, ids, context=None):
        pp_obj = self.pool['product.product']
        pplv_obj = self.pool['product.pricelist.version']
        ppli_obj = self.pool['product.pricelist.item']
        for pspiuw in self.browse(cr, uid, ids, context=context):
            pp = pp_obj.browse(cr, uid, pspiuw.product_id.id, context=context)
            pplv = pplv_obj.browse(cr,
                                   uid,
                                   pspiuw.pricelist_version_id.id,
                                   context=context)
            item_id = False
            for item in pplv.items_id:
                if item.product_id.id == pp.id:
                    item_id = item.id
            if item_id:
                if pspiuw.specific_price == 0:
                    # Unlink specific price
                    ppli_obj.unlink(cr, uid, [item_id], context=context)
                # Update specific price
                ppli_obj.write(cr,
                               uid, [item_id], {
                                   'price_surcharge': pspiuw.specific_price,
                               },
                               context=context)
            else:
                # Create new item
                ppli_obj.create(cr,
                                uid, {
                                    'name': pp.code,
                                    'product_id': pspiuw.product_id.id,
                                    'company_id': pplv.company_id.id,
                                    'price_version_id': pplv.id,
                                    'base': 1,
                                    'price_discount': -1,
                                    'price_surcharge': pspiuw.specific_price,
                                },
                                context=context)

        return True
import time

from openerp.osv import orm, fields
from openerp.addons import decimal_precision as dp

FISCAL_RULE_COLUMNS = {
    'partner_fiscal_type_id': fields.many2one(
        'l10n_br_account.partner.fiscal.type', 'Tipo Fiscal do Parceiro'),
    'fiscal_category_id': fields.many2one('l10n_br_account.fiscal.category',
                                          'Categoria', requeried=True),
    'fiscal_type': fields.selection(
        [('1', 'Simples Nacional'),
         ('2', 'Simples Nacional – excesso de sublimite de receita bruta'),
         ('3', 'Regime Normal')], 'Regime Tributário', required=True),
    'revenue_start': fields.float('Faturamento Inicial',
                                  digits_compute=dp.get_precision('Account'),
                                  help="Faixa inicial de faturamento bruto"),
    'revenue_end': fields.float('Faturamento Final',
                                digits_compute=dp.get_precision('Account'),
                                help="Faixa inicial de faturamento bruto")
}

FISCAL_RULE_DEFAULTS = {
    'fiscal_type': '3',
    'revenue_start': 0.00,
    'revenue_end': 0.00
}


class account_fiscal_position_rule_template(orm.Model):
    _inherit = 'account.fiscal.position.rule.template'
Beispiel #34
0
class account_invoice_line(osv.Model):
    _inherit = "account.invoice.line"

    def _amount_line_tax(self, cr, uid, line, price, context=None):
        """
            Calculando el subtotal con impuestos
        """
        val = 0.0

        # Se llama para redondear la cantindad
        cur_obj = self.pool.get('res.currency')

        # Calculando impuestos
        for c in self.pool.get('account.tax').compute_all(
                cr, uid, line.invoice_line_tax_id, price, 1, line.product_id,
                line.partner_id)['taxes']:
            val += c.get('amount', 0.0)
        cur = line.invoice_id.currency_id or 0.0

        print """""" """""" """"cur:  """, cur

        if cur:
            # Regresando el valor de los impuestos redondeado
            return cur_obj.round(cr, uid, cur, val)
        else:
            return 0.0

    def _compute_tax_all(self, cr, uid, ids, field_names, args, context=None):
        """
            Calculando importe con descuentos: comercial, volumen, mezcla; además del cálculo del total neto con
            descuento financiero
        """
        res = {}
        amount_subtotal_desc = 0.0
        discount_subtotal_sale = 0.0
        price_discount = 0.0
        imprt_discount = 0.0
        dif = 0.0
        utility_c = 0.0
        utility_div = 0.0
        utility_p = 0.0

        for line in self.browse(cr, uid, ids, context=context):
            res[line.id] = {
                'price_unit_discount': 0.0,
                'price_subtotal2': 0.0,
                'diference': 0.0,
                'total_cost': 0.0,
                'utility': 0.0,
                'utility_percent': 0.0,
            }

            # Se obtiene el importe o subtotal
            price = line.price_subtotal

            # Aplica al subtotal el descuento comercial
            if line.discount_com > 0:
                discount_sale = price * (line.discount_com / 100)
                price = price - discount_sale
            # Aplica al subtotal el descuento de mezcla
            if line.discount_mez > 0:
                discount_sale = price * (line.discount_mez / 100)
                price = price - discount_sale
            # Aplica al subtotal el descuento de volumen
            if line.discount_vol > 0:
                discount_sale = price * (line.discount_vol / 100)
                price = price - discount_sale
            # Aplica al subtotal el descuento de financiero
            if line.discount_fin > 0:
                discount_sale = price * (line.discount_fin / 100)
                price = price - discount_sale

            print "********** PRICE ********* ", price
            # Se agrega el nuevo importe con los descuentos (comercial, volumen, mezcla) al diccionario
            res[line.id]['price_subtotal2'] = price

            # Calculamos el precio del producto con descuentos aplicados
            res[line.id]['price_unit_discount'] = (price / line.quantity)

            # Calculamos la diferencia de importes
            res[line.id]['diference'] = line.price_subtotal - res[
                line.id]['price_subtotal2']

            # Obtiene el costo total
            res[line.id]['total_cost'] = line.standard_price * line.quantity

            # Calcula la utilidad
            utility = price - res[line.id]['total_cost']
            res[line.id]['utility'] = utility
            res[line.id]['utility_percent'] = (
                utility / price) * 100 if utility != 0 and price != 0 else 0.0
        return res

    _columns = {
        # Descuentos aplicados sobre la linea
        'discount_com':
        fields.float('Comercial',
                     digits_compute=dp.get_precision('Account'),
                     readonly=True),
        'discount_vol':
        fields.float('Volumen',
                     digits_compute=dp.get_precision('Account'),
                     readonly=True),
        'discount_mez':
        fields.float('Mezcla',
                     digits_compute=dp.get_precision('Account'),
                     readonly=True),
        'discount_fin':
        fields.float('Financiero',
                     digits_compute=dp.get_precision('Account'),
                     readonly=True),

        # Campos para reporte de ventas
        'price_unit_discount':
        fields.function(_compute_tax_all,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='Precio C/Desc (unitario)',
                        method=True,
                        store=True,
                        multi='amount_all'),
        'price_subtotal2':
        fields.function(_compute_tax_all,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='Importe C/Desc',
                        method=True,
                        store=True,
                        multi='amount_all'),
        'diference':
        fields.function(_compute_tax_all,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='Diferencia',
                        method=True,
                        store=True,
                        multi='amount_all'),
        'total_cost':
        fields.function(_compute_tax_all,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        store=True,
                        string='Total costo',
                        method=True,
                        multi="amount_all"),
        'utility':
        fields.function(_compute_tax_all,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='Utilidad',
                        store=True,
                        method=True,
                        multi="amount_all"),
        'utility_percent':
        fields.function(_compute_tax_all,
                        type='float',
                        digits_compute=dp.get_precision('Account'),
                        string='%Utilidad',
                        method=True,
                        store=True,
                        multi='amount_all'),
    }
Beispiel #35
0
class product_product(osv.osv):
    _inherit = "product.product"

    def _stock_move_count(self, cr, uid, ids, field_name, arg, context=None):
        res = dict([(id, {
            'reception_count': 0,
            'delivery_count': 0
        }) for id in ids])
        move_pool = self.pool.get('stock.move')
        moves = move_pool.read_group(cr, uid,
                                     [('product_id', 'in', ids),
                                      ('picking_id.type', '=', 'in'),
                                      ('state', 'in',
                                       ('confirmed', 'assigned', 'pending'))],
                                     ['product_id'], ['product_id'])
        for move in moves:
            product_id = move['product_id'][0]
            res[product_id]['reception_count'] = move['product_id_count']
        moves = move_pool.read_group(cr, uid,
                                     [('product_id', 'in', ids),
                                      ('picking_id.type', '=', 'out'),
                                      ('state', 'in',
                                       ('confirmed', 'assigned', 'pending'))],
                                     ['product_id'], ['product_id'])
        for move in moves:
            product_id = move['product_id'][0]
            res[product_id]['delivery_count'] = move['product_id_count']
        return res

    def get_product_accounts(self, cr, uid, product_id, context=None):
        """ To get the stock input account, stock output account and stock journal related to product.
        @param product_id: product id
        @return: dictionary which contains information regarding stock input account, stock output account and stock journal
        """
        if context is None:
            context = {}
        product_obj = self.pool.get('product.product').browse(cr,
                                                              uid,
                                                              product_id,
                                                              context=context)

        stock_input_acc = product_obj.property_stock_account_input and product_obj.property_stock_account_input.id or False
        if not stock_input_acc:
            stock_input_acc = product_obj.categ_id.property_stock_account_input_categ and product_obj.categ_id.property_stock_account_input_categ.id or False

        stock_output_acc = product_obj.property_stock_account_output and product_obj.property_stock_account_output.id or False
        if not stock_output_acc:
            stock_output_acc = product_obj.categ_id.property_stock_account_output_categ and product_obj.categ_id.property_stock_account_output_categ.id or False

        journal_id = product_obj.categ_id.property_stock_journal and product_obj.categ_id.property_stock_journal.id or False
        account_valuation = product_obj.categ_id.property_stock_valuation_account_id and product_obj.categ_id.property_stock_valuation_account_id.id or False
        return {
            'stock_account_input': stock_input_acc,
            'stock_account_output': stock_output_acc,
            'stock_journal': journal_id,
            'property_stock_valuation_account_id': account_valuation
        }

    def do_change_standard_price(self, cr, uid, ids, datas, context=None):
        """ Changes the Standard Price of Product and creates an account move accordingly.
        @param datas : dict. contain default datas like new_price, stock_output_account, stock_input_account, stock_journal
        @param context: A standard dictionary
        @return:

        """
        location_obj = self.pool.get('stock.location')
        move_obj = self.pool.get('account.move')
        move_line_obj = self.pool.get('account.move.line')
        if context is None:
            context = {}

        new_price = datas.get('new_price', 0.0)
        stock_output_acc = datas.get('stock_output_account', False)
        stock_input_acc = datas.get('stock_input_account', False)
        journal_id = datas.get('stock_journal', False)
        move_ids = []
        loc_ids = location_obj.search(cr, uid, [('usage', '=', 'internal')])
        for product in self.browse(cr, uid, ids, context=context):
            if product.valuation != 'real_time':
                continue
            account_valuation = product.categ_id.property_stock_valuation_account_id
            account_valuation_id = account_valuation and account_valuation.id or False
            if not account_valuation_id:
                raise osv.except_osv(
                    _('Error!'),
                    _('Specify valuation Account for Product Category: %s.') %
                    (product.categ_id.name))
            for location in location_obj.browse(cr,
                                                uid,
                                                loc_ids,
                                                context=context):
                c = context.copy()
                c.update({'location': location.id, 'compute_child': False})

                # qty_available depends of the location in the context
                qty = self.read(cr,
                                uid, [product.id], ['qty_available'],
                                context=c)[0]['qty_available']

                diff = product.standard_price - new_price
                if not diff:
                    raise osv.except_osv(
                        _('Error!'),
                        _("No difference between standard price and new price!"
                          ))
                if qty:
                    company_id = location.company_id and location.company_id.id or False
                    if not company_id:
                        raise osv.except_osv(
                            _('Error!'),
                            _('Please specify company in Location.'))
                    #
                    # Accounting Entries
                    #
                    if not journal_id:
                        journal_id = product.categ_id.property_stock_journal and product.categ_id.property_stock_journal.id or False
                    if not journal_id:
                        raise osv.except_osv(_('Error!'),
                            _('Please define journal '\
                              'on the product category: "%s" (id: %d).') % \
                                (product.categ_id.name,
                                    product.categ_id.id,))
                    move_id = move_obj.create(cr, uid, {
                        'journal_id': journal_id,
                        'company_id': company_id
                    })

                    move_ids.append(move_id)

                    if diff > 0:
                        if not stock_input_acc:
                            stock_input_acc = product.\
                                property_stock_account_input.id
                        if not stock_input_acc:
                            stock_input_acc = product.categ_id.\
                                    property_stock_account_input_categ.id
                        if not stock_input_acc:
                            raise osv.except_osv(_('Error!'),
                                    _('Please define stock input account ' \
                                            'for this product: "%s" (id: %d).') % \
                                            (product.name,
                                                product.id,))
                        amount_diff = qty * diff
                        move_line_obj.create(
                            cr, uid, {
                                'name': product.name,
                                'account_id': stock_input_acc,
                                'debit': amount_diff,
                                'move_id': move_id,
                            })
                        move_line_obj.create(
                            cr, uid, {
                                'name': product.categ_id.name,
                                'account_id': account_valuation_id,
                                'credit': amount_diff,
                                'move_id': move_id
                            })
                    elif diff < 0:
                        if not stock_output_acc:
                            stock_output_acc = product.\
                                property_stock_account_output.id
                        if not stock_output_acc:
                            stock_output_acc = product.categ_id.\
                                    property_stock_account_output_categ.id
                        if not stock_output_acc:
                            raise osv.except_osv(_('Error!'),
                                    _('Please define stock output account ' \
                                            'for this product: "%s" (id: %d).') % \
                                            (product.name,
                                                product.id,))
                        amount_diff = qty * -diff
                        move_line_obj.create(
                            cr, uid, {
                                'name': product.name,
                                'account_id': stock_output_acc,
                                'credit': amount_diff,
                                'move_id': move_id
                            })
                        move_line_obj.create(
                            cr, uid, {
                                'name': product.categ_id.name,
                                'account_id': account_valuation_id,
                                'debit': amount_diff,
                                'move_id': move_id
                            })
        self.write(cr, uid, ids, {'standard_price': new_price})

        return move_ids

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

    def get_product_available(self, cr, uid, ids, context=None):
        """ Finds whether product is available or not in particular warehouse.
        @return: Dictionary of values
        """
        if context is None:
            context = {}

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

        states = context.get('states', [])
        what = context.get('what', ())
        if not ids:
            ids = self.search(cr, uid, [])
        res = {}.fromkeys(ids, 0.0)
        if not ids:
            return res

        if context.get('shop', False):
            warehouse_id = shop_obj.read(cr, uid, int(context['shop']),
                                         ['warehouse_id'])['warehouse_id'][0]
            if warehouse_id:
                context['warehouse'] = warehouse_id

        if context.get('warehouse', False):
            lot_id = warehouse_obj.read(cr, uid, int(context['warehouse']),
                                        ['lot_stock_id'])['lot_stock_id'][0]
            if lot_id:
                context['location'] = lot_id

        if context.get('location', False):
            if type(context['location']) == type(1):
                location_ids = [context['location']]
            elif type(context['location']) in (type(''), type(u'')):
                location_ids = location_obj.search(
                    cr,
                    uid, [('name', 'ilike', context['location'])],
                    context=context)
            else:
                location_ids = context['location']
        else:
            location_ids = []
            wids = warehouse_obj.search(cr, uid, [], context=context)
            if not wids:
                return res
            for w in warehouse_obj.browse(cr, uid, wids, context=context):
                location_ids.append(w.lot_stock_id.id)

        # build the list of ids of children of the location given by id
        if context.get('compute_child', True):
            child_location_ids = location_obj.search(
                cr, uid, [('location_id', 'child_of', location_ids)])
            location_ids = child_location_ids or location_ids

        # this will be a dictionary of the product UoM by product id
        product2uom = {}
        uom_ids = []
        for product in self.read(cr, uid, ids, ['uom_id'], context=context):
            product2uom[product['id']] = product['uom_id'][0]
            uom_ids.append(product['uom_id'][0])
        # this will be a dictionary of the UoM resources we need for conversion purposes, by UoM id
        uoms_o = {}
        for uom in self.pool.get('product.uom').browse(cr,
                                                       uid,
                                                       uom_ids,
                                                       context=context):
            uoms_o[uom.id] = uom

        results = []
        results2 = []

        from_date = context.get('from_date', False)
        to_date = context.get('to_date', False)
        date_str = False
        date_values = False
        where = [
            tuple(location_ids),
            tuple(location_ids),
            tuple(ids),
            tuple(states)
        ]
        if from_date and to_date:
            date_str = "date>=%s and date<=%s"
            where.append(tuple([from_date]))
            where.append(tuple([to_date]))
        elif from_date:
            date_str = "date>=%s"
            date_values = [from_date]
        elif to_date:
            date_str = "date<=%s"
            date_values = [to_date]
        if date_values:
            where.append(tuple(date_values))

        prodlot_id = context.get('prodlot_id', False)
        prodlot_clause = ''
        if prodlot_id:
            prodlot_clause = ' and prodlot_id = %s '
            where += [prodlot_id]

        # TODO: perhaps merge in one query.
        if 'in' in what:
            # all moves from a location out of the set to a location in the set
            cr.execute(
                'select sum(product_qty), product_id, product_uom '\
                'from stock_move '\
                'where location_id NOT IN %s '\
                'and location_dest_id IN %s '\
                'and product_id IN %s '\
                'and state IN %s ' + (date_str and 'and '+date_str+' ' or '') +' '\
                + prodlot_clause +
                'group by product_id,product_uom',tuple(where))
            results = cr.fetchall()
        if 'out' in what:
            # all moves from a location in the set to a location out of the set
            cr.execute(
                'select sum(product_qty), product_id, product_uom '\
                'from stock_move '\
                'where location_id IN %s '\
                'and location_dest_id NOT IN %s '\
                'and product_id  IN %s '\
                'and state in %s ' + (date_str and 'and '+date_str+' ' or '') + ' '\
                + prodlot_clause +
                'group by product_id,product_uom',tuple(where))
            results2 = cr.fetchall()

        # Get the missing UoM resources
        uom_obj = self.pool.get('product.uom')
        uoms = map(lambda x: x[2], results) + map(lambda x: x[2], results2)
        if context.get('uom', False):
            uoms += [context['uom']]
        uoms = filter(lambda x: x not in uoms_o.keys(), uoms)
        if uoms:
            uoms = uom_obj.browse(cr, uid, list(set(uoms)), context=context)
            for o in uoms:
                uoms_o[o.id] = o

        #TOCHECK: before change uom of product, stock move line are in old uom.
        context.update({'raise-exception': False})
        # Count the incoming quantities
        for amount, prod_id, prod_uom in results:
            amount = uom_obj._compute_qty_obj(cr,
                                              uid,
                                              uoms_o[prod_uom],
                                              amount,
                                              uoms_o[context.get('uom', False)
                                                     or product2uom[prod_id]],
                                              context=context)
            res[prod_id] += amount
        # Count the outgoing quantities
        for amount, prod_id, prod_uom in results2:
            amount = uom_obj._compute_qty_obj(cr,
                                              uid,
                                              uoms_o[prod_uom],
                                              amount,
                                              uoms_o[context.get('uom', False)
                                                     or product2uom[prod_id]],
                                              context=context)
            res[prod_id] -= amount
        return res

    def _product_available(self,
                           cr,
                           uid,
                           ids,
                           field_names=None,
                           arg=False,
                           context=None):
        """ Finds the incoming and outgoing quantity of product.
        @return: Dictionary of values
        """
        if not field_names:
            field_names = []
        if context is None:
            context = {}
        res = {}
        for id in ids:
            res[id] = {}.fromkeys(field_names, 0.0)
        for f in field_names:
            c = context.copy()
            if f == 'qty_available':
                c.update({'states': ('done', ), 'what': ('in', 'out')})
            if f == 'virtual_available':
                c.update({
                    'states': ('confirmed', 'waiting', 'assigned', 'done'),
                    'what': ('in', 'out')
                })
            if f == 'incoming_qty':
                c.update({
                    'states': ('confirmed', 'waiting', 'assigned'),
                    'what': ('in', )
                })
            if f == 'outgoing_qty':
                c.update({
                    'states': ('confirmed', 'waiting', 'assigned'),
                    'what': ('out', )
                })
            stock = self.get_product_available(cr, uid, ids, context=c)
            for id in ids:
                res[id][f] = stock.get(id, 0.0)
        return res

    _columns = {
        'reception_count': fields.function(_stock_move_count, string="Reception", type='integer', multi='pickings'),
        'delivery_count': fields.function(_stock_move_count, string="Delivery", type='integer', multi='pickings'),
        'qty_available': fields.function(_product_available, multi='qty_available',
            type='float',  digits_compute=dp.get_precision('Product Unit of Measure'),
            string='Quantity On Hand',
            help="Current quantity of products.\n"
                 "In a context with a single Stock Location, this includes "
                 "goods stored at this Location, or any of its children.\n"
                 "In a context with a single Warehouse, this includes "
                 "goods stored in the Stock Location of this Warehouse, or any "
                 "of its children.\n"
                 "In a context with a single Shop, this includes goods "
                 "stored in the Stock Location of the Warehouse of this Shop, "
                 "or any of its children.\n"
                 "Otherwise, this includes goods stored in any Stock Location "
                 "with 'internal' type."),
        'virtual_available': fields.function(_product_available, multi='qty_available',
            type='float',  digits_compute=dp.get_precision('Product Unit of Measure'),
            string='Forecasted Quantity',
            help="Forecast quantity (computed as Quantity On Hand "
                 "- Outgoing + Incoming)\n"
                 "In a context with a single Stock Location, this includes "
                 "goods stored in this location, or any of its children.\n"
                 "In a context with a single Warehouse, this includes "
                 "goods stored in the Stock Location of this Warehouse, or any "
                 "of its children.\n"
                 "In a context with a single Shop, this includes goods "
                 "stored in the Stock Location of the Warehouse of this Shop, "
                 "or any of its children.\n"
                 "Otherwise, this includes goods stored in any Stock Location "
                 "with 'internal' type."),
        'incoming_qty': fields.function(_product_available, multi='qty_available',
            type='float',  digits_compute=dp.get_precision('Product Unit of Measure'),
            string='Incoming',
            help="Quantity of products that are planned to arrive.\n"
                 "In a context with a single Stock Location, this includes "
                 "goods arriving to this Location, or any of its children.\n"
                 "In a context with a single Warehouse, this includes "
                 "goods arriving to the Stock Location of this Warehouse, or "
                 "any of its children.\n"
                 "In a context with a single Shop, this includes goods "
                 "arriving to the Stock Location of the Warehouse of this "
                 "Shop, or any of its children.\n"
                 "Otherwise, this includes goods arriving to any Stock "
                 "Location with 'internal' type."),
        'outgoing_qty': fields.function(_product_available, multi='qty_available',
            type='float',  digits_compute=dp.get_precision('Product Unit of Measure'),
            string='Outgoing',
            help="Quantity of products that are planned to leave.\n"
                 "In a context with a single Stock Location, this includes "
                 "goods leaving this Location, or any of its children.\n"
                 "In a context with a single Warehouse, this includes "
                 "goods leaving the Stock Location of this Warehouse, or "
                 "any of its children.\n"
                 "In a context with a single Shop, this includes goods "
                 "leaving the Stock Location of the Warehouse of this "
                 "Shop, or any of its children.\n"
                 "Otherwise, this includes goods leaving any Stock "
                 "Location with 'internal' type."),
        'track_production': fields.boolean('Track Manufacturing Lots', help="Forces to specify a Serial Number for all moves containing this product and generated by a Manufacturing Order"),
        'track_incoming': fields.boolean('Track Incoming Lots', help="Forces to specify a Serial Number for all moves containing this product and coming from a Supplier Location"),
        'track_outgoing': fields.boolean('Track Outgoing Lots', help="Forces to specify a Serial Number for all moves containing this product and going to a Customer Location"),
        'location_id': fields.dummy(string='Location', relation='stock.location', type='many2one'),
        'warehouse_id': fields.dummy(string='Warehouse', relation='stock.warehouse', type='many2one'),
        'valuation':fields.selection([('manual_periodic', 'Periodical (manual)'),
                                        ('real_time','Real Time (automated)'),], 'Inventory Valuation',
                                        help="If real-time valuation is enabled for a product, the system will automatically write journal entries corresponding to stock moves." \
                                             "The inventory variation account set on the product category will represent the current inventory value, and the stock input and stock output account will hold the counterpart moves for incoming and outgoing products."
                                        , required=True),
    }

    _defaults = {
        'valuation': 'manual_periodic',
    }

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

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

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

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

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

                if location_info.usage == 'production':
                    if fields.get('virtual_available'):
                        res['fields']['virtual_available']['string'] = _(
                            'Future Productions')
                    if fields.get('qty_available'):
                        res['fields']['qty_available']['string'] = _(
                            'Produced Qty')
        return res
Beispiel #36
0
class crossovered_budget_lines(models.Model):
    _inherit = "crossovered.budget.lines"

    @api.multi
    @api.depends('general_budget_id', 'general_budget_id.account_ids',
                 'date_to', 'date_from', 'analytic_account_id')
    def _get_practical_amount(self):
        account_obj = self.pool.get('account.account')
        for line in self:
            result = 0.0
            acc_ids = [x.id for x in line.general_budget_id.account_ids]
            if not acc_ids:
                raise UserError(
                    _("Error! The Budget '%s' has no accounts!") %
                    ustr(line.general_budget_id.name))
            acc_ids = account_obj._get_children_and_consol(
                self._cr, self._uid, acc_ids, context=self._context)
            date_to = line.date_to
            date_from = line.date_from
            crossovered_budget_id = line.crossovered_budget_id

            if crossovered_budget_id and isinstance(crossovered_budget_id.id,
                                                    (NewId)):
                continue

            costcenter = crossovered_budget_id and crossovered_budget_id.cost_center_id or None
            if costcenter and date_from and date_to:
                self._cr.execute(
                    "SELECT SUM(debit) - SUM(credit) FROM account_move_line WHERE cost_center_budget_id=%s AND (date "
                    "between to_date(%s,'yyyy-mm-dd') AND to_date(%s,'yyyy-mm-dd')) AND "
                    "account_id=%s ",
                    (crossovered_budget_id.id, date_from, date_to,
                     line.general_budget_id.account_id.id))
                result = self._cr.fetchone()[0]
            elif line.analytic_account_id and date_from and date_to:
                self._cr.execute(
                    "SELECT SUM(amount) FROM account_analytic_line WHERE account_id=%s AND (date "
                    "between to_date(%s,'yyyy-mm-dd') AND to_date(%s,'yyyy-mm-dd')) AND "
                    "general_account_id=ANY(%s)", (
                        line.analytic_account_id.id,
                        date_from,
                        date_to,
                        acc_ids,
                    ))
                result = self._cr.fetchone()[0]
            if result is None:
                result = 0.00
            line.practical_amount = result

    practical_amount = fields.Float(compute='_get_practical_amount',
                                    string='Practical Amount',
                                    digits_compute=dp.get_precision('Account'))

    @api.multi
    def unlink(self):
        for line in self:
            result = None
            crossovered_budget_id = line.crossovered_budget_id
            date_to = line.date_to
            date_from = line.date_from
            costcenter = crossovered_budget_id and crossovered_budget_id.cost_center_id or None
            if costcenter and date_from and date_to:
                self._cr.execute(
                    "SELECT id FROM account_move_line WHERE cost_center_budget_id=%s AND (date "
                    "between to_date(%s,'yyyy-mm-dd') AND to_date(%s,'yyyy-mm-dd')) AND "
                    "account_id=%s ",
                    (crossovered_budget_id.id, date_from, date_to,
                     line.general_budget_id.account_id.id))
                result = self._cr.fetchone()
            if result:
                warning_msg = _(
                    'Is not possible to delete the budget line because journal entries are posted on the account!'
                )
                raise UserError(warning_msg)
            super(crossovered_budget_lines, line).unlink()
        return True
Beispiel #37
0
class stock_move(osv.osv):
    _inherit = 'stock.move'

    def _cal_move_weight(self, cr, uid, ids, name, args, context=None):
        res = {}
        uom_obj = self.pool.get('product.uom')
        for move in self.browse(cr, uid, ids, context=context):
            weight = weight_net = 0.00
            if move.product_id.weight > 0.00:
                converted_qty = move.product_qty
                weight = (converted_qty * move.product_id.weight)

                if move.product_id.weight_net > 0.00:
                    weight_net = (converted_qty * move.product_id.weight_net)

            res[move.id] = {
                'weight': weight,
                'weight_net': weight_net,
            }
        return res

    _columns = {
        'weight':
        fields.function(_cal_move_weight,
                        type='float',
                        string='Weight',
                        digits_compute=dp.get_precision('Stock Weight'),
                        multi='_cal_move_weight',
                        store={
                            'stock.move':
                            (lambda self, cr, uid, ids, c=None: ids,
                             ['product_id', 'product_uom_qty',
                              'product_uom'], 30),
                        }),
        'weight_net':
        fields.function(_cal_move_weight,
                        type='float',
                        string='Net weight',
                        digits_compute=dp.get_precision('Stock Weight'),
                        multi='_cal_move_weight',
                        store={
                            'stock.move':
                            (lambda self, cr, uid, ids, c=None: ids,
                             ['product_id', 'product_uom_qty',
                              'product_uom'], 30),
                        }),
        'weight_uom_id':
        fields.many2one(
            'product.uom',
            'Unit of Measure',
            required=True,
            readonly="1",
            help=
            "Unit of Measure (Unit of Measure) is the unit of measurement for Weight",
        ),
    }

    def action_confirm(self, cr, uid, ids, context=None):
        """
            Pass the carrier to the picking from the sales order
            (Should also work in case of Phantom BoMs when on explosion the original move is deleted)
        """
        procs_to_check = []
        for move in self.browse(cr, uid, ids, context=context):
            if move.procurement_id and move.procurement_id.sale_line_id and move.procurement_id.sale_line_id.order_id.carrier_id:
                procs_to_check += [move.procurement_id]
        res = super(stock_move, self).action_confirm(cr,
                                                     uid,
                                                     ids,
                                                     context=context)
        pick_obj = self.pool.get("stock.picking")
        for proc in procs_to_check:
            pickings = list(
                set([
                    x.picking_id.id for x in proc.move_ids
                    if x.picking_id and not x.picking_id.carrier_id
                ]))
            if pickings:
                pick_obj.write(
                    cr,
                    uid,
                    pickings,
                    {'carrier_id': proc.sale_line_id.order_id.carrier_id.id},
                    context=context)
        return res

    def _get_default_uom(self, cr, uid, context=None):
        uom_categ_id = self.pool.get('ir.model.data').xmlid_to_res_id(
            cr, uid, 'product.product_uom_categ_kgm')
        return self.pool.get('product.uom').search(
            cr, uid, [('category_id', '=', uom_categ_id),
                      ('factor', '=', 1)])[0]

    _defaults = {
        'weight_uom_id':
        lambda self, cr, uid, c: self._get_default_uom(cr, uid, c),
    }
            }
            val = val1 = 0.0
            cur = order.pricelist_id.currency_id
            for line in order.order_line:
                val1 += line.price_subtotal
                val += self._amount_line_tax(cr, uid, line, context=context)
            res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val)
            res[order.id]['amount_untaxed'] = cur_obj.round(cr, uid, cur, val1)
            res[order.id]['amount_total'] = res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
        return res

    _columns = {
        'tot_volume': fields.function(_tot_volume, string='Total Volume', type='float'),
        'avg_volume': fields.function(_avg_volume, string='Average Volume', type='float'),
        'calculated' : fields.boolean('Amount Calculated'),
        'amount_untaxed': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Untaxed Amount',
            store={
                'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line', 'calculated'], 10),
                'sale.order.line': (_get_order, ['purchase_price','price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
            },
            multi='sums', help="The amount without tax.", track_visibility='always'),
        'amount_tax': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Taxes',
            store={
                'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10),
                'sale.order.line': (_get_order, ['purchase_price', 'price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
            },
            multi='sums', help="The tax amount."),
        'amount_total': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Total',
            store={
                'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line', 'calculated'], 10),
                'sale.order.line': (_get_order, ['purchase_price', 'price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
Beispiel #39
0
class stock_picking(osv.osv):
    _inherit = 'stock.picking'

    def _cal_weight(self, cr, uid, ids, name, args, context=None):
        res = {}
        for picking in self.browse(cr, uid, ids, context=context):
            total_weight = total_weight_net = 0.00

            for move in picking.move_lines:
                total_weight += move.weight
                total_weight_net += move.weight_net

            res[picking.id] = {
                'weight': total_weight,
                'weight_net': total_weight_net,
            }
        return res

    def _get_picking_line(self, cr, uid, ids, context=None):
        result = {}
        for line in self.pool.get('stock.move').browse(cr,
                                                       uid,
                                                       ids,
                                                       context=context):
            result[line.picking_id.id] = True
        return result.keys()

    _columns = {
        'carrier_id':
        fields.many2one("delivery.carrier", "Carrier"),
        'volume':
        fields.float('Volume'),
        'weight':
        fields.function(_cal_weight,
                        type='float',
                        string='Weight',
                        digits_compute=dp.get_precision('Stock Weight'),
                        multi='_cal_weight',
                        store={
                            'stock.picking':
                            (lambda self, cr, uid, ids, c={}: ids,
                             ['move_lines'], 40),
                            'stock.move': (_get_picking_line, [
                                'picking_id', 'product_id', 'product_uom_qty',
                                'product_uom'
                            ], 40),
                        }),
        'weight_net':
        fields.function(_cal_weight,
                        type='float',
                        string='Net Weight',
                        digits_compute=dp.get_precision('Stock Weight'),
                        multi='_cal_weight',
                        store={
                            'stock.picking':
                            (lambda self, cr, uid, ids, c={}: ids,
                             ['move_lines'], 40),
                            'stock.move': (_get_picking_line, [
                                'picking_id', 'product_id', 'product_uom_qty',
                                'product_uom'
                            ], 40),
                        }),
        'carrier_tracking_ref':
        fields.char('Carrier Tracking Ref'),
        'number_of_packages':
        fields.integer('Number of Packages'),
        'weight_uom_id':
        fields.many2one(
            'product.uom',
            'Unit of Measure',
            required=True,
            readonly="1",
            help="Unit of measurement for Weight",
        ),
    }

    def _prepare_shipping_invoice_line(self,
                                       cr,
                                       uid,
                                       picking,
                                       invoice,
                                       context=None):
        """Prepare the invoice line to add to the shipping costs to the shipping's
           invoice.

            :param browse_record picking: the stock picking being invoiced
            :param browse_record invoice: the stock picking's invoice
            :return: dict containing the values to create the invoice line,
                     or None to create nothing
        """
        carrier_obj = self.pool.get('delivery.carrier')
        grid_obj = self.pool.get('delivery.grid')
        if not picking.carrier_id or \
            any(inv_line.product_id.id == picking.carrier_id.product_id.id
                for inv_line in invoice.invoice_line):
            return None
        grid_id = carrier_obj.grid_get(cr,
                                       uid, [picking.carrier_id.id],
                                       picking.partner_id.id,
                                       context=context)
        if not grid_id:
            raise osv.except_osv(_('Warning!'),
                    _('The carrier %s (id: %d) has no delivery grid!') \
                            % (picking.carrier_id.name,
                                picking.carrier_id.id))
        quantity = sum([line.product_uom_qty for line in picking.move_lines])
        price = grid_obj.get_price_from_picking(cr,
                                                uid,
                                                grid_id,
                                                invoice.amount_untaxed,
                                                picking.weight,
                                                picking.volume,
                                                quantity,
                                                context=context)
        account_id = picking.carrier_id.product_id.property_account_income.id
        if not account_id:
            account_id = picking.carrier_id.product_id.categ_id\
                    .property_account_income_categ.id

        taxes = picking.carrier_id.product_id.taxes_id
        partner = picking.partner_id or False
        if partner:
            account_id = self.pool.get('account.fiscal.position').map_account(
                cr, uid, partner.property_account_position, account_id)
            taxes_ids = self.pool.get('account.fiscal.position').map_tax(
                cr, uid, partner.property_account_position, taxes)
        else:
            taxes_ids = [x.id for x in taxes]

        return {
            'name': picking.carrier_id.name,
            'invoice_id': invoice.id,
            'uos_id': picking.carrier_id.product_id.uos_id.id,
            'product_id': picking.carrier_id.product_id.id,
            'account_id': account_id,
            'price_unit': price,
            'quantity': 1,
            'invoice_line_tax_id': [(6, 0, taxes_ids)],
        }

    def _create_invoice_from_picking(self,
                                     cr,
                                     uid,
                                     picking,
                                     vals,
                                     context=None):
        invoice_obj = self.pool.get('account.invoice')
        invoice_line_obj = self.pool.get('account.invoice.line')
        invoice_id = super(stock_picking,
                           self)._create_invoice_from_picking(cr,
                                                              uid,
                                                              picking,
                                                              vals,
                                                              context=context)
        invoice = invoice_obj.browse(cr, uid, invoice_id, context=context)
        invoice_line = self._prepare_shipping_invoice_line(cr,
                                                           uid,
                                                           picking,
                                                           invoice,
                                                           context=context)
        if invoice_line:
            invoice_line_obj.create(cr, uid, invoice_line)
        return invoice_id

    def _get_default_uom(self, cr, uid, context=None):
        uom_categ_id = self.pool.get('ir.model.data').xmlid_to_res_id(
            cr, uid, 'product.product_uom_categ_kgm')
        return self.pool.get('product.uom').search(
            cr, uid, [('category_id', '=', uom_categ_id),
                      ('factor', '=', 1)])[0]

    _defaults = {
        'weight_uom_id':
        lambda self, cr, uid, c: self._get_default_uom(cr, uid, c),
    }
import time

from openerp.osv import orm, fields
from openerp.addons import decimal_precision as dp
from .res_company import COMPANY_FISCAL_TYPE, COMPANY_FISCAL_TYPE_DEFAULT

FISCAL_RULE_COLUMNS = {
    'partner_fiscal_type_id': fields.many2one(
        'l10n_br_account.partner.fiscal.type', 'Tipo Fiscal do Parceiro'),
    'fiscal_category_id': fields.many2one(
        'l10n_br_account.fiscal.category', 'Categoria'),
    'fiscal_type': fields.selection(COMPANY_FISCAL_TYPE,
        u'Regime Tributário', required=True),
    'revenue_start': fields.float(
        'Faturamento Inicial', digits_compute=dp.get_precision('Account'),
        help="Faixa inicial de faturamento bruto"),
    'revenue_end': fields.float(
        'Faturamento Final', digits_compute=dp.get_precision('Account'),
        help="Faixa inicial de faturamento bruto")
}

OTHERS_FISCAL_RULE_COLUMNS_TEMPLATE = {
    'parent_id': fields.many2one(
            'account.fiscal.position.rule.template', 'Regra Pai'),
    'child_ids': fields.one2many(
            'account.fiscal.position.rule.template',
            'parent_id', 'Regras Filhas'),
}

OTHERS_FISCAL_RULE_COLUMNS = {
class product_product_ext_lot(osv.Model):
    _inherit = 'product.product'

    def get_base_uom(self, cr, uid, ids, context=None):
        ''' Returns the UOM which is the reference for the UOM
            of this product.

            This method must receive just one ID, or a list with just
            one ID, because all the others will be ignored.
        '''
        if context is None:
            context = {}
        if not isinstance(ids, list):
            ids = [ids]

        uom_obj = self.pool.get('product.uom')

        product = self.browse(cr, uid, ids[0], context=context)
        uom_ids = uom_obj.search(
            cr,
            uid, [('category_id', '=', product.uom_id.category_id.id),
                  ('uom_type', '=', 'reference')],
            context=context)

        # If we don't find the UOM is is the base one, we will return False.
        base_uom = False
        if uom_ids:
            base_uom = uom_obj.browse(cr, uid, uom_ids[0], context=context)
        return base_uom

    def get_lots_available(self, cr, uid, ids, context=None):
        ''' Returns the list of stock.production.lots which have a use_date which
            is greater than today, or which is not set, for the current product.
            The result is sorted by 'life_date ASC, use_date ASC, date ASC'
        '''
        if context is None:
            context = {}
        if not isinstance(ids, list):
            ids = ids[0]

        stock_production_lot_obj = self.pool.get('stock.production.lot')

        product = self.browse(cr, uid, ids[0], context=context)

        lot_ids = stock_production_lot_obj.search(
            cr,
            uid, [('product_id', '=', product.id), '|',
                  ('use_date', '>', fields.datetime.now()),
                  ('use_date', '=', False)],
            order='life_date ASC, use_date ASC, create_date ASC',
            context=context)
        lots = stock_production_lot_obj.browse(cr,
                                               uid,
                                               lot_ids,
                                               context=context)

        return lots

    def _get_lot_date(self, cr, uid, product, lot, field, context=None):
        lot_creation_date = lot.production_date and datetime.datetime.strptime(
            lot.production_date, DEFAULT_SERVER_DATETIME_FORMAT)
        lot_use_date = lot.use_date and datetime.datetime.strptime(
            lot.use_date, DEFAULT_SERVER_DATETIME_FORMAT)

        duration_create = getattr(product, field[0])
        date_create = duration_create and lot_creation_date + datetime.timedelta(
            days=duration_create) or None

        duration_end = None
        if lot_use_date:
            if field[0] in ('alert_time', 'removal_time'):
                f = field[0]
                if f == 'removal_time':
                    f = 'block_time'
                f = 'expiration_{0}'.format(f)
                v = float(getattr(product, f))
                u = getattr(product, '{0}_uom'.format(f))
                if u and v:
                    duration_end = self._expiration_uom(cr,
                                                        uid,
                                                        False,
                                                        u,
                                                        v,
                                                        context=context)
        date_end = duration_end and lot_use_date + duration_end or None
        if date_end is None or date_create is not None and date_create < date_end:
            return date_create
        else:
            return date_end

    def check_product_lot_expiry_dates(self,
                                       cr,
                                       uid,
                                       locations_to_consider=None,
                                       context=None):
        ''' Checks the expiration-related dates of all the lots which belong to products,
            only if the name of the location of the lot is within the list 'locations_to_consider'.
        '''
        if context is None:
            context = {}
        if locations_to_consider is None:
            locations_to_consider = []

        product_obj = self.pool.get("product.product")
        lot_obj = self.pool.get("stock.production.lot")
        revision_obj = self.pool.get("stock.production.lot.revision")
        issue_obj = self.pool.get("project.issue")
        product_ids = product_obj.search(cr, uid, [], context=context)
        # (product, lot, message, priority, color -1=ignore
        date_fields = (
            ('alert_time', 'alert_date',
             _('This product lot is near its removal date'), 4, -1),
            ('removal_time', 'removal_date',
             _('Attention: This product lot must be removed from sell'), 3, 3),
            ('use_time', 'use_date',
             _('Warning: This product lot must not be used after this date'),
             2, 2),
            ('life_time', 'life_date',
             _('Danger: This product lot has exceeded its safety life-time!'),
             1, 2),
        )
        lots_under_review = []
        for product in product_obj.browse(cr,
                                          uid,
                                          product_ids,
                                          context=context):
            for prodlot in product.stock_prodlots:
                if (not prodlot.prodlot_id) or (prodlot.qty <= 0) or (
                        prodlot.location_id.location_id.name
                        not in locations_to_consider):
                    continue
                # For any lot under revision, we update the date fields if required
                lot = prodlot.prodlot_id
                lots_under_review.append(lot.id)
                logger.debug("Checking product {0}\tlot {1}".format(
                    product.name, lot.name))
                for field in date_fields:
                    if not getattr(lot, field[1]):
                        date = self._get_lot_date(cr,
                                                  uid,
                                                  product,
                                                  lot,
                                                  field,
                                                  context=context)
                        if date and date < datetime.datetime.today():
                            msg = _(
                                'Updating lot date {0}, with value {1}, because it has been exceeded'
                            ).format(field[1], date)
                            # logger.debug(msg)
                            lot_obj.write(
                                cr,
                                uid,
                                lot.id, {
                                    field[1]:
                                    date.strftime(
                                        DEFAULT_SERVER_DATETIME_FORMAT)
                                },
                                context=context)
                            lot_obj.message_post(cr,
                                                 uid,
                                                 lot.id,
                                                 msg,
                                                 context=context)
        for lot_id in lots_under_review:
            lot = lot_obj.browse(cr, uid, lot_id, context=context)
            for field in date_fields:
                has_revision = False
                for revision in lot.revisions:
                    if revision.indice == field[1]:
                        has_revision = True
                        break
                if has_revision:
                    continue
                date_field_value = getattr(lot, field[1])
                if not date_field_value:
                    continue
                date = datetime.datetime.strptime(
                    date_field_value, DEFAULT_SERVER_DATETIME_FORMAT)
                if date < datetime.datetime.today():
                    values = {
                        'name': field[2],
                        'description': None,
                        'indice': field[1],
                        'lot_id': lot.id,
                    }
                    revision_obj.create(cr, uid, values, context=context)
                    issue_ids = issue_obj.find_resource_issues(
                        cr,
                        uid,
                        'stock.production.lot',
                        lot.id,
                        tags=['lot', 'lot-production-date'],
                        create=True,
                        reopen=True,
                        context=context)
                    for issue in issue_obj.browse(cr,
                                                  uid,
                                                  issue_ids,
                                                  context=context):
                        issue.message_post(field[2])
                        if int(issue.priority) > field[3]:
                            issue.write({'priority': str(field[3])})
                            if field[4] >= 0:
                                issue.write({'color': field[4]})

    @api.one
    def onchange_check_decimals(self, value, decimal_accuracy_class):
        return self.product_tmpl_id.onchange_check_decimals(
            value, decimal_accuracy_class)

    def _compute_packing(self, cr, uid, ids, field_name, arg, context=None):
        ''' Computes the 'packing' for a product.
            The packing is the multiplication of product's lenght X width X height X weight.
        '''
        if context is None:
            context = {}
        res = {}
        for product in self.browse(cr, uid, ids, context=context):
            res[product.
                id] = product.length * product.width * product.height * product.weight
        return res

    def _virtual_stock_calculation(self,
                                   cr,
                                   uid,
                                   ids,
                                   field,
                                   arg,
                                   context=None):
        ''' Calculates the several measures which are used to keep track of the quantity which is available.
        '''
        if context is None:
            context = {}

        ret = {}

        product_uom_obj = self.pool.get('product.uom')

        for product in self.browse(cr, uid, ids, context=context):

            qty_on_reservation_quotations = 0

            for reservation in product.draft_sale_order_lines:
                # The lines in the sale.order store the quantity in the UOM indicated
                # by the sale.order. But the Quantity on Hand and all the other fields
                # related to quantities which are shown on the product's form are in the
                # unit of measure of the product. Thus, we must convert it to that UOM.
                qty_product_uom = product_uom_obj._compute_qty(
                    cr, uid, reservation.product_uom.id,
                    reservation.product_uom_qty, product.uom_id.id)
                qty_on_reservation_quotations += qty_product_uom

            ret[product.id] = {
                'product_reservation_qty':
                qty_on_reservation_quotations,
                'qty_on_sale':
                product.qty_available - qty_on_reservation_quotations -
                abs(product.outgoing_qty),
            }

        return ret

    def _get_last_inventory(self, cr, uid, ids, field, arg=None, context=None):
        res = {}
        line_obj = self.pool.get('stock.inventory.line')
        for _id in ids:
            res[_id] = False
            for line_id in line_obj.search(cr,
                                           uid, [('product_id', '=', _id),
                                                 ('state', '=', 'done')],
                                           order='inventory_id DESC',
                                           limit=1):
                res[_id] = line_obj.read(cr,
                                         uid,
                                         line_id, ['inventory_id'],
                                         context=context)['inventory_id']
        return res

    _columns = {
        # Attributes related to the features a product can have.
        'weight':
        fields.float("Weight",
                     digits_compute=dp.get_precision('Stock Weight')),
        'length':
        fields.float('Length',
                     digits_compute=dp.get_precision('Stock Length'),
                     help='Length of the product (in centimeters)'),
        'width':
        fields.float('Width',
                     digits_compute=dp.get_precision('Stock Width'),
                     help='Width of the product (in centimeters)'),
        'height':
        fields.float('Height',
                     digits_compute=dp.get_precision('Stock Height'),
                     help='Height of the product (in centimeters)'),
        'diameter':
        fields.float('Diameter',
                     digits_compute=dp.get_precision('Stock Diameter'),
                     help='Diameter of the product (in centimeters)'),
        'packing':
        fields.function(
            _compute_packing,
            string='Packing',
            readonly=True,
            digits_compute=dp.get_precision('Stock Packing'),
            store={
                'product.product': (lambda self, cr, uid, ids, context: ids,
                                    ['length', 'width', 'height',
                                     'weight'], 10)
            },
            help='Length x Width x Height x Weight (gross, not net)'),
        'brand':
        fields.char('Brand', help='The brand of the product'),
        'manufacturer_website':
        fields.char('Manufacturer\'s Website',
                    help='Link to the manufacturer\'s web site.'),
        'stock_prodlots':
        fields.related('last_inventory_id',
                       'line_ids',
                       type='one2many',
                       relation='stock.inventory.line',
                       string='Stock report by serial number',
                       readonly=True,
                       domain=[('product_id', '=', 'id')]),
        'last_inventory_id':
        fields.function(_get_last_inventory,
                        string="Last inventory",
                        type='many2one',
                        relation='stock.inventory',
                        store=False),
        'product_reservation_qty':
        fields.function(
            _virtual_stock_calculation,
            type="float",
            string="Reservations (on Quotations)",
            readonly=True,
            multi='_virtual_stock_calculation',
            help=
            'It shows the amount which is on sale.order lines which are in state draft, thus corresponding to '
            'quotations which are in state draft. This is useful to keep track of units which are not available '
            'because of having been reserved for an order from the shop, for example.'
        ),
        'qty_on_sale':
        fields.function(
            _virtual_stock_calculation,
            type="float",
            string="Quantity Available",
            readonly=True,
            multi='_virtual_stock_calculation',
            help=
            "It is computed as 'Quantity On Hand' - 'Reservations (on Quotations)' - 'Outgoing'."
        ),
        'draft_sale_order_lines':
        fields.one2many('sale.order.line',
                        'product_id',
                        domain=[('state', 'in', ['draft'])],
                        string='Appearance in quotations',
                        readonly=True),
        'webshop_state':
        fields.selection(
            [('', '<not active>'), ('on_sale', 'On Sale'),
             ('visible', 'Not on sale, but visible'),
             ('not_visible', 'Not visible'),
             ('not_visible_conditional', 'Not visible if quantity is 0')],
            'Webshop State',
            help='The possible states for a product in a webshop.'),

        # The following variable (target_state) was extracted from the
        # original product's life-cycle: It was found that not all the clients
        # needed nor wanted that module, but anyway those variables were still needed
        # by some of the other modules they did need; thus they was placed here
        # in the very-top module of the connector.
        'target_state':
        fields.selection([('inactive', 'Inactive'), ('active', 'Active')],
                         string="Target State",
                         required=True),
    }

    _defaults = {
        'target_state': 'inactive',
        'weight': 0.00,
    }
    # Fields for Ship From
    from_country = fields.Many2one('res.country','Country')
    from_postal_code = fields.Char('Postal Code')
    from_residential = fields.Boolean('Residential',default=False)

    # Fields for Recipient
    recipient_id = fields.Many2one('res.partner','Recipient Partner',help="This field is optional.If not filled you can manually set the address")
    to_country = fields.Many2one('res.country','Country',select=True)
    to_country_code = fields.Char(related="to_country.code",string='Country Code')
    to_postal_code = fields.Char('Postal Code')
    to_residential = fields.Boolean('Residential',default=False)
    response = fields.Text(
                           'Response')
    #International Shipment
    commodity_lines = fields.One2many('rate.commodity.package','request_id','Commodities')
    customs_value = fields.Float(compute = _compute_total_customs,string = "Total Customs Value",readonly=True,digits=dp.get_precision('Account'))
    customs_currency = fields.Selection(fedex_lists._fedex_currency,'Customs Currency',default="USD")
    B13AFilingOption = fields.Selection([('FEDEX_TO_STAMP','FedEx to Stamp'),
                                         ('FILED_ELECTRONICALLY','Filed Electronically'),
                                         ('MANUALLY_ATTACHED','Manually Attached'),
                                         ('NOT_REQUIRED','Not Required'),
                                         ('SUMMARY_REPORTING','Summary Reporting')],'B13A Filing Option',default="NOT_REQUIRED")

    special_services_type = fields.Selection([('COD','COD')],string = "Request Special Services")
    cod_collection_type = fields.Selection([('ANY','Any'),
                                            ('CASH','Cash'),
                                            ('COMPANY_CHECK','Company Check'),
                                            ('GUARANTEED_FUNDS','Guarunteed'),
                                            ('PERSONAL_CHECK','Personal Check')
                                            ],'Collection Type')
    cod_currency = fields.Selection(fedex_lists._fedex_currency,string = "COD Currency",default="CAD")
class account_voucher(osv.osv):
    _inherit = 'account.voucher'

    _columns = {
        'customer_amount':
        fields.float(
            'Customer Payment',
            help=
            "Specify the customer payment value. Value specified here will be used in contra entry for payment journal.",
            digits_compute=dp.get_precision('Account'),
            required=False,
            readonly=True,
            states={'draft': [('readonly', False)]}),
        'supplier_amount':
        fields.float(
            'Supplier Payment',
            help=
            "Specify the supplier payment value. Value specified here will be used in contra entry for payment journal.",
            digits_compute=dp.get_precision('Account'),
            required=False,
            readonly=True,
            states={'draft': [('readonly', False)]}),
    }

    def recompute_voucher_lines(self,
                                cr,
                                uid,
                                ids,
                                partner_id,
                                journal_id,
                                price,
                                currency_id,
                                ttype,
                                date,
                                context=None):
        """
        Returns a dict that contains new values and context

        @param partner_id: latest value from user input for field partner_id
        @param args: other arguments
        @param context: context arguments, like lang, time zone

        @return: Returns a dict which contains new values, and context
        """
        def _remove_noise_in_o2m():
            """if the line is partially reconciled, then we must pay attention to display it only once and
                in the good o2m.
                This function returns True if the line is considered as noise and should not be displayed
            """
            if line.reconcile_partial_id:
                if currency_id == line.currency_id.id:
                    if line.amount_residual_currency <= 0:
                        return True
                else:
                    if line.amount_residual <= 0:
                        return True
            return False

        if not context.get('mode', False) == 'partner':
            return super(account_voucher,
                         self).recompute_voucher_lines(cr,
                                                       uid,
                                                       ids,
                                                       partner_id,
                                                       journal_id,
                                                       price,
                                                       currency_id,
                                                       ttype,
                                                       date,
                                                       context=context)

        if context is None:
            context = {}
        context_multi_currency = context.copy()
        if date:
            context_multi_currency.update({'date': date})

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

        #set default values
        default = {
            'value': {
                'line_dr_ids': [],
                'line_cr_ids': [],
                'pre_line': False,
            },
        }

        #drop existing lines
        line_ids = ids and line_pool.search(
            cr, uid, [('voucher_id', '=', ids[0])]) or False
        if line_ids:
            line_pool.unlink(cr, uid, line_ids)

        if not partner_id or not journal_id:
            return default

        journal = journal_pool.browse(cr, uid, journal_id, context=context)
        partner = partner_pool.browse(cr, uid, partner_id, context=context)
        currency_id = currency_id or journal.company_id.currency_id.id
        account_id = False
        if journal.type in ('sale', 'sale_refund'):
            account_id = partner.property_account_receivable.id
        elif journal.type in ('purchase', 'purchase_refund', 'expense'):
            account_id = partner.property_account_payable.id
        else:
            account_id = journal.default_credit_account_id.id or journal.default_debit_account_id.id

        default['value']['account_id'] = account_id

        if journal.type not in ('cash', 'bank'):
            return default

        total_credit = 0.0
        total_debit = 0.0
        account_type = 'receivable'
        if ttype == 'payment':
            account_type = 'payable'
            total_debit = price or 0.0
        else:
            total_credit = price or 0.0
            account_type = 'receivable'

        if not context.get('move_line_ids', False):
            ids = move_line_pool.search(
                cr,
                uid, [('state', '=', 'valid'),
                      ('account_id.type', '=', account_type),
                      ('reconcile_id', '=', False),
                      ('partner_id', '=', partner_id)],
                context=context)
        else:
            ids = context['move_line_ids']

        if context.get('mode', False) == 'partner':
            account_type = ('receivable', 'payable')
            ids = move_line_pool.search(
                cr,
                uid, [('state', '=', 'valid'),
                      ('account_id.type', 'in', account_type),
                      ('reconcile_id', '=', False),
                      ('partner_id', '=', partner_id)],
                context=context)

        invoice_id = context.get('invoice_id', False)
        company_currency = journal.company_id.currency_id.id
        move_line_found = False

        #order the lines by most old first
        ids.reverse()
        account_move_lines = move_line_pool.browse(cr,
                                                   uid,
                                                   ids,
                                                   context=context)

        #compute the total debit/credit and look for a matching open amount or invoice
        for line in account_move_lines:
            if _remove_noise_in_o2m():
                continue

            if invoice_id:
                if line.invoice.id == invoice_id:
                    #if the invoice linked to the voucher line is equal to the invoice_id in context
                    #then we assign the amount on that line, whatever the other voucher lines
                    move_line_found = line.id
                    break
            elif currency_id == company_currency:
                #otherwise treatments is the same but with other field names
                if line.amount_residual == price:
                    #if the amount residual is equal the amount voucher, we assign it to that voucher
                    #line, whatever the other voucher lines
                    move_line_found = line.id
                    break
                #otherwise we will split the voucher amount on each line (by most old first)
                total_credit += line.credit or 0.0
                total_debit += line.debit or 0.0
            elif currency_id == line.currency_id.id:
                if line.amount_residual_currency == price:
                    move_line_found = line.id
                    break
                total_credit += line.credit and line.amount_currency or 0.0
                total_debit += line.debit and line.amount_currency or 0.0

        #voucher line creation
        for line in account_move_lines:

            if _remove_noise_in_o2m():
                continue

            if line.currency_id and currency_id == line.currency_id.id:
                amount_original = abs(line.amount_currency)
                amount_unreconciled = abs(line.amount_residual_currency)
            else:
                amount_original = currency_pool.compute(
                    cr, uid, company_currency, currency_id, line.credit
                    or line.debit or 0.0)
                amount_unreconciled = currency_pool.compute(
                    cr, uid, company_currency, currency_id,
                    abs(line.amount_residual))
            line_currency_id = line.currency_id and line.currency_id.id or company_currency
            rs = {
                'name':
                line.move_id.name,
                'type':
                line.credit and 'dr' or 'cr',
                'move_line_id':
                line.id,
                'account_id':
                line.account_id.id,
                'amount_original':
                amount_original,
                'amount': (move_line_found == line.id)
                and min(abs(price), amount_unreconciled) or 0.0,
                'date_original':
                line.date,
                'date_due':
                line.date_maturity,
                'amount_unreconciled':
                amount_unreconciled,
                'currency_id':
                line_currency_id,
            }
            #in case a corresponding move_line hasn't been found, we now try to assign the voucher amount
            #on existing invoices: we split voucher amount by most old first, but only for lines in the same currency
            if not move_line_found:
                if currency_id == line_currency_id:
                    if line.credit:
                        amount = min(amount_unreconciled, abs(total_debit))
                        rs['amount'] = amount
                        total_debit -= amount
                    else:
                        amount = min(amount_unreconciled, abs(total_credit))
                        rs['amount'] = amount
                        total_credit -= amount

            if rs['amount_unreconciled'] == rs['amount']:
                rs['reconcile'] = True

            if rs['type'] == 'cr':
                default['value']['line_cr_ids'].append(rs)
            else:
                default['value']['line_dr_ids'].append(rs)

            if ttype == 'payment' and len(default['value']['line_cr_ids']) > 0:
                default['value']['pre_line'] = 1
            elif ttype == 'receipt' and len(
                    default['value']['line_dr_ids']) > 0:
                default['value']['pre_line'] = 1
            default['value'][
                'writeoff_amount'] = self._compute_writeoff_amount(
                    cr, uid, default['value']['line_dr_ids'],
                    default['value']['line_cr_ids'], price, ttype)
        return default

    def action_move_line_create(self, cr, uid, ids, context=None):
        '''
        Confirm the vouchers given in ids and create the journal entries for each of them
        '''
        if context is None:
            context = {}
        move_pool = self.pool.get('account.move')
        move_line_pool = self.pool.get('account.move.line')
        for voucher in self.browse(cr, uid, ids, context=context):
            if voucher.move_id:
                continue
            company_currency = self._get_company_currency(
                cr, uid, voucher.id, context)
            current_currency = self._get_current_currency(
                cr, uid, voucher.id, context)
            # we select the context to use accordingly if it's a multicurrency case or not
            context = self._sel_context(cr, uid, voucher.id, context)
            # But for the operations made by _convert_amount, we always need to give the date in the context
            ctx = context.copy()
            ctx.update({'date': voucher.date})
            # Create the account move record.
            move_id = move_pool.create(cr,
                                       uid,
                                       self.account_move_get(cr,
                                                             uid,
                                                             voucher.id,
                                                             context=context),
                                       context=context)
            # Get the name of the account_move just created
            name = move_pool.browse(cr, uid, move_id, context=context).name
            # Create the first line of the voucher
            move_line_id = move_line_pool.create(
                cr, uid,
                self.first_move_line_get(cr, uid, voucher.id, move_id,
                                         company_currency, current_currency,
                                         context), context)
            move_line_brw = move_line_pool.browse(cr,
                                                  uid,
                                                  move_line_id,
                                                  context=context)
            line_total = move_line_brw.debit - move_line_brw.credit
            rec_list_ids = []
            if voucher.type == 'sale':
                line_total = line_total - self._convert_amount(
                    cr, uid, voucher.tax_amount, voucher.id, context=ctx)
            elif voucher.type == 'purchase':
                line_total = line_total + self._convert_amount(
                    cr, uid, voucher.tax_amount, voucher.id, context=ctx)
            # Create one move line per voucher line where amount is not 0.0
            line_total, rec_list_ids = self.voucher_move_line_create(
                cr, uid, voucher.id, line_total, move_id, company_currency,
                current_currency, context)

            # Create the writeoff line if needed
            ml_writeoff = self.writeoff_move_line_get(cr, uid, voucher.id,
                                                      line_total, move_id,
                                                      name, company_currency,
                                                      current_currency,
                                                      context)
            if ml_writeoff:
                move_line_pool.create(cr, uid, ml_writeoff, context)
            # We post the voucher.
            self.write(cr, uid, [voucher.id], {
                'move_id': move_id,
                'state': 'posted',
                'number': name,
            })
            if voucher.journal_id.entry_posted:
                move_pool.post(cr, uid, [move_id], context={})
            # We automatically reconcile the account move lines.
            reconcile = False
            for rec_ids in rec_list_ids:
                if len(rec_ids) >= 2:
                    reconcile = move_line_pool.reconcile_partial(
                        cr,
                        uid,
                        rec_ids,
                        writeoff_acc_id=voucher.writeoff_acc_id.id,
                        writeoff_period_id=voucher.period_id.id,
                        writeoff_journal_id=voucher.journal_id.id)
        return True


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Beispiel #44
0
# -*- coding: utf-8 -*-

import time
from datetime import date
from datetime import datetime
from dateutil.relativedelta import relativedelta

from openerp.osv import fields, osv, orm
import openerp.addons.decimal_precision as dp

DP = dp.get_precision('Brokers')


class ResUser(orm.Model):

    _inherit = 'res.users'

    _columns = {
        'contractor_id': fields.many2one(
            'res.partner',
            string='Canal de Distribución'
        )
    }


class InsuranceParentesco(orm.Model):
    _name = 'insurance.parentesco'
    _description = 'Parentezco de Deudores'
    _columns = {
        'name': fields.char('Parentesco', size=32, required=True),
        'conyugue': fields.boolean('Conyugue ?')
Beispiel #45
0
class account_invoice_with_discount(models.Model):

    _inherit = 'account.invoice'
    '''
    Questa funzione sostituisce quella di base per il calcolo dei totali della fattura.
    '''
    @api.one
    @api.depends('invoice_line.price_subtotal', 'invoice_line.free',
                 'tax_line.amount', 'global_discount_lines')
    def _compute_amount(self):
        cur_obj = self.pool.get('res.currency')
        cur = self.currency_id
        tax_lines = {}

        #VALORIZZO I VARI RISULTATI, COME LO SAREBBERO NELLA FUNZIONE BASE
        self.amount_untaxed = sum(line.price_subtotal
                                  for line in self.invoice_line)
        self.amount_tax = sum(line.amount for line in self.tax_line)
        self.amount_total = self.amount_untaxed + self.amount_tax
        self.amount_untaxed_free = 0
        self.amount_tax_free = 0

        temporary_untaxed_value = 0.0
        temporary_global_discount_total = 0.0
        temporary_showed_global_discount_total = 0.0
        original_untaxed_value = 0.0
        original_total_value = 0.0
        original_tax_value = 0.0

        for line in self.invoice_line:
            original_untaxed_value = 0.0
            original_total_value = 0.0
            original_tax_value = 0.0

            temporary_untaxed_value += line.price_subtotal
            '''
            SE LA RIGA E' UN OMAGGIO, INCREMENTO L'IMPORTO TOTALE DEGLI OMAGGI DELL'IMPONIBILE DELLA RIGA STESSA (SENZA SCONTO)
            INOLTRE, SE SI TRATTA DI UN OMAGGIO CON RIVALSA, MEMORIZZO LA RIGA DI TASSE ASSOCIATA ALLA RIGA DI FATTURA, POICHE' 
            ANCHE TALI TASSE DOVRANNO ESSERE OMAGGIATE
            '''
            if line.free in ['gift', 'base_gift']:
                self.amount_untaxed_free += line.price_subtotal
                if line.free == 'gift':
                    for tax in line.invoice_line_tax_id:
                        if tax.amount in tax_lines:
                            tax_lines[tax.amount] += line.price_subtotal
                        else:
                            tax_lines[tax.amount] = line.price_subtotal
            '''
            NEL CASO IN CUI LA RIGA NON SIA UN OMAGGIO, SIA LEGATA AD UN PRODOTTO E TALE PRODOTTO AMMETTA IL CALCOLO DEGLI SCONTI GLOBALI, NE RICALCOLO L'IMPONIBILE, 
            L'IMPORTO IN TASSE ED IL TOTALE, APPLICANDOVI SEQUENZIALMENTE TUTTI GLI SCONTI GLOBALI
            '''
            if line.free not in [
                    'gift', 'base_gift'
            ] and (not line.product_id or
                   (line.product_id and not line.product_id.no_discount)):

                for tax in line.invoice_line_tax_id:
                    original_tax_value += line.price_subtotal * tax.amount
                original_untaxed_value = line.price_subtotal
                original_total_value = original_untaxed_value + original_tax_value

                for discount in self.global_discount_lines:

                    val = original_tax_value
                    val1 = original_untaxed_value
                    val2 = original_total_value

                    if discount.type == 'fisso':
                        temporary_global_discount_total += discount.value
                        temporary_showed_global_discount_total += discount.value
                        perc = discount.value / val1
                    else:
                        perc = discount.value / 100

                    sc = val * perc
                    val -= sc
                    sc1 = val1 * perc
                    val1 -= sc1

                    if discount.type == 'perc':
                        temporary_global_discount_total += sc + sc1
                        temporary_showed_global_discount_total += sc1

                    original_tax_value = cur_obj.round(self._cr, self._uid,
                                                       cur, val)
                    original_untaxed_value = cur_obj.round(
                        self._cr, self._uid, cur, val1)
                    original_total_value = original_tax_value + original_untaxed_value

        #CALCOLO IL TOTALE DI TASSE OMAGGIO
        for tl in tax_lines:
            self.amount_tax_free += tax_lines[tl] * tl

        #CALCOLO, IN PERCENTUALE, A QUANTO AMMONTA LO SCONTO TOTALE
        if self.amount_total:
            if original_untaxed_value + temporary_showed_global_discount_total:
                self.global_discount_percentual = temporary_showed_global_discount_total / (
                    original_untaxed_value +
                    temporary_showed_global_discount_total)
        else:
            self.global_discount_percentual = 0.0

        self.showed_global_discount_total = temporary_showed_global_discount_total
        self.global_discount_total = temporary_global_discount_total
        self.amount_tax = self.amount_tax - self.amount_tax_free - (
            temporary_global_discount_total -
            temporary_showed_global_discount_total)
        self.amount_untaxed = temporary_untaxed_value - temporary_showed_global_discount_total - self.amount_untaxed_free
        self.amount_total = self.amount_tax + self.amount_untaxed

    #COLUMNS

    global_discount_lines = fields.One2many('account.invoice.discount',
                                            'account_id',
                                            string='Sconti Globali')
    global_discount_total = fields.Float(string='Totale Sconti',
                                         digits=dp.get_precision('Account'),
                                         store=True,
                                         readonly=True,
                                         compute='_compute_amount')
    showed_global_discount_total = fields.Float(
        string='Totale Sconti',
        digits=dp.get_precision('Account'),
        store=True,
        readonly=True,
        compute='_compute_amount')
    global_discount_percentual = fields.Float(string='Totale Sconti (%)',
                                              store=True,
                                              readonly=True,
                                              compute='_compute_amount')
    amount_untaxed = fields.Float(string='Subtotal',
                                  digits=dp.get_precision('Account'),
                                  store=True,
                                  readonly=True,
                                  compute='_compute_amount',
                                  track_visibility='always')
    amount_tax = fields.Float(string='Tax',
                              digits=dp.get_precision('Account'),
                              store=True,
                              readonly=True,
                              compute='_compute_amount')
    amount_total = fields.Float(string='Total',
                                digits=dp.get_precision('Account'),
                                store=True,
                                readonly=True,
                                compute='_compute_amount')
    '''
    QUESTA FUNZIONE SI INSERISCE NEL FLUSSO DI CREAZIONE DELLE RIGHE DI MOVIMENTAZIONE CONTABILI ALLA VALIDAZIONE DI UNA FATTURA
    '''

    @api.multi
    def finalize_invoice_move_lines(self, move_lines):
        '''
        Chiamiamo la super per reperire le move_lines da creare. Tuttavia, osserviamo che gli importi di queste move_lines non sono quelli corretti, poiché già 
        ridotti degli sconti. Noi desideriamo che le righe contabili in questa fase non siano ridotte degli sconti perché intendiamo stornare gli sconti con delle
        righe apposite
        '''
        move_lines = super(account_invoice_with_discount,
                           self).finalize_invoice_move_lines(move_lines)

        tax_obj = self.pool.get('account.tax')
        self._cr.execute(
            '''SELECT inv.showed_global_discount_total, inv.global_discount_total, inv.amount_total, jour.type FROM account_invoice AS inv, account_journal AS jour WHERE inv.id = %s AND jour.id = inv.journal_id''',
            (self.id, ))
        t = self._cr.fetchall()[0]
        showed_global_discount_total = t[0]
        global_discount_total = t[1]
        amount_total = t[2]
        type = t[3]

        #Qualora la fattura presenti degli sconti globali, bisogna rivalorizzare le righe contabili già esistenti ed eventualmente creare righe contabili di storno
        if showed_global_discount_total > 0.0:
            if not (self.env.user.company_id.discount_untaxed_account_id
                    and self.env.user.company_id.discount_tax_account_id):
                raise Warning(
                    _("No discount accounts defined for this company"))

            # ricalcoliamo le scadenze, poi creiamo un dizionario con chiave 'data di scadenza' e come valore la somma degli importi di tutte le righe che scadono in quella data
            ctx = {}
            for item in self._context.items():
                ctx[item[0]] = item[1]
            if self._name == 'account.invoice':
                ctx['invoice_id'] = self.id

            totlines = self.with_context(ctx).payment_term.compute(
                amount_total, self.date_invoice)[0]

            dict = {}
            for tl in totlines:
                if tl[0] in dict:
                    dict[tl[0]] += tl[1]
                else:
                    dict[tl[0]] = tl[1]
            '''
            Ricalcoliamo i totali di 'debito' e 'credito' delle righe, in modo che non risultino già stornate nel loro importo. Inoltre, reperiamo i dati relativi ai conti 
            contabili da utilizzare.
            '''
            tax_code_id = None
            base_code_id = None

            for ml in move_lines:
                ml_maturity = ml[2]['date_maturity']
                if ml_maturity in dict:
                    if type in ['sale', 'purchase_refund']:
                        ml[2]['debit'] = dict[ml[2]['date_maturity']]
                    elif type in ['purchase', 'sale_refund']:
                        ml[2]['credit'] = dict[ml[2]['date_maturity']]

                if not tax_code_id:
                    if 'tax_code_id' in ml[2] and ml[2]['tax_code_id']:
                        tax_ids = tax_obj.search(
                            self._cr, self._uid,
                            [('tax_code_id', '=', ml[2]['tax_code_id'])],
                            self._context)
                        if tax_ids and len(tax_ids) and tax_ids[0]:
                            tax_code_id = ml[2]['tax_code_id']
                if not base_code_id:
                    if 'tax_code_id' in ml[2] and ml[2]['tax_code_id']:
                        tax_ids = tax_obj.search(
                            self._cr, self._uid,
                            [('base_code_id', '=', ml[2]['tax_code_id'])],
                            self._context)
                        if tax_ids and len(tax_ids) and tax_ids[0]:
                            base_code_id = ml[2]['tax_code_id']

            #Se siamo in presenza di sconti, creiamo una riga di storno imponibile
            if showed_global_discount_total:
                # riga imponibile omaggio
                new_line = {
                    'analytic_account_id':
                    False,
                    'tax_code_id':
                    base_code_id or False,
                    'analytic_lines': [],
                    'tax_amount': (type in ['sale', 'purchase_refund']
                                   and -showed_global_discount_total)
                    or (type in ['purchase', 'sale_refund']
                        and showed_global_discount_total),
                    'name':
                    _('"Discount" Amount'),
                    'ref':
                    '',
                    'currency_id':
                    False,
                    'debit':
                    type in ['sale', 'purchase_refund']
                    and showed_global_discount_total,
                    'product_id':
                    False,
                    'date_maturity':
                    False,
                    'credit':
                    type in ['purchase', 'sale_refund']
                    and showed_global_discount_total,
                    'date':
                    move_lines[0][2]['date'],
                    'amount_currency':
                    0,
                    'product_uom_id':
                    False,
                    'quantity':
                    1,
                    'partner_id':
                    move_lines[0][2]['partner_id'],
                    'account_id':
                    (self.env.user.company_id.discount_untaxed_account_id.id),
                }
                move_lines += [(0, 0, new_line)]

            #Se lo sconto ha comportato anche una riduzione dell'imposta, creiamo una riga di storno imposta.
            if global_discount_total - showed_global_discount_total > 0.0:
                # riga iva omaggio
                # if precision_diff > 0.0:
                new_line = {
                    'analytic_account_id':
                    False,
                    'tax_code_id':
                    tax_code_id or False,
                    'analytic_lines': [],
                    'tax_amount':
                    (type in ['sale', 'purchase_refund'] and
                     -(global_discount_total - showed_global_discount_total))
                    or
                    (type in ['purchase', 'sale_refund'] and
                     (global_discount_total - showed_global_discount_total)),
                    'name':
                    _('"Discount" Tax Amount'),
                    'ref':
                    '',
                    'currency_id':
                    False,
                    'debit':
                    type in ['sale', 'purchase_refund']
                    and (global_discount_total - showed_global_discount_total),
                    'product_id':
                    False,
                    'date_maturity':
                    False,
                    'credit':
                    type in ['purchase', 'sale_refund']
                    and (global_discount_total - showed_global_discount_total),
                    'date':
                    move_lines[0][2]['date'],
                    'amount_currency':
                    0,
                    'product_uom_id':
                    False,
                    'quantity':
                    1,
                    'partner_id':
                    move_lines[0][2]['partner_id'],
                    'account_id':
                    (self.env.user.company_id.discount_tax_account_id.id),
                }
                move_lines += [(0, 0, new_line)]

            #Reperiamo i totali di debito e credito calcolati sommando tutte le righe contabili fin qui presenti
            tot_debit = 0.0
            tot_credit = 0.0
            for line in move_lines:
                if line[2]['credit'] and line[2]['credit'] > 0.0:
                    tot_credit += line[2]['credit']
                if line[2]['debit'] and line[2]['debit'] > 0.0:
                    tot_debit += line[2]['debit']
            '''        
            Poiché potrebbero esserci errori di arrotondamento in seguito ai calcoli degli sconti, (si considera errore di arrotondamento un valore compreso tra 0 e 0.01)
            incrementiamo o riduciamo (a seconda che l'errore sia in eccesso o in difetto) l'importo di debito o credito dell'ultima riga contabile (a seconda che tale 
            riga abbia valorizzata la colonna di credito o debito). 
            '''
            if abs(round(tot_debit - tot_credit, 2)) <= 0.01 and abs(
                    round(tot_debit - tot_credit, 2)) > 0.0:
                prv = abs(round(tot_debit - tot_credit, 2))
                if tot_debit > tot_credit:
                    if showed_global_discount_total and global_discount_total - showed_global_discount_total > 0.0:
                        if move_lines[-2][2]['debit']:
                            move_lines[-2][2].update({
                                'debit':
                                move_lines[-2][2]['debit'] -
                                round(tot_debit - tot_credit, 2)
                            })
                        elif move_lines[-2][2]['credit']:
                            move_lines[-2][2].update({
                                'credit':
                                move_lines[-2][2]['credit'] +
                                round(tot_debit - tot_credit, 2)
                            })
                    else:
                        if move_lines[-1][2]['debit']:
                            move_lines[-1][2].update({
                                'debit':
                                move_lines[-1][2]['debit'] -
                                round(tot_debit - tot_credit, 2)
                            })
                        elif move_lines[-1][2]['credit']:
                            move_lines[-1][2].update({
                                'credit':
                                move_lines[-1][2]['credit'] +
                                round(tot_debit - tot_credit, 2)
                            })
                else:
                    if showed_global_discount_total and global_discount_total - showed_global_discount_total > 0.0:
                        if move_lines[-2][2]['debit']:
                            move_lines[-2][2].update({
                                'debit':
                                move_lines[-2][2]['debit'] +
                                round(tot_credit - tot_debit, 2)
                            })
                        elif move_lines[-2][2]['credit']:
                            move_lines[-2][2].update({
                                'credit':
                                move_lines[-2][2]['credit'] -
                                round(tot_credit - tot_debit, 2)
                            })
                    else:
                        if move_lines[-1][2]['debit']:
                            move_lines[-1][2].update({
                                'debit':
                                move_lines[-1][2]['debit'] +
                                round(tot_credit - tot_debit, 2)
                            })
                        elif move_lines[-1][2]['credit']:
                            move_lines[-1][2].update({
                                'credit':
                                move_lines[-1][2]['credit'] -
                                round(tot_credit - tot_debit, 2)
                            })

        return move_lines
Beispiel #46
0
    def compute_landed_cost(self, cr, uid, ids, context=None):
        line_obj = self.pool.get("stock.valuation.adjustment.lines")
        unlink_ids = line_obj.search(cr, uid, [("cost_id", "in", ids)], context=context)
        line_obj.unlink(cr, uid, unlink_ids, context=context)
        digits = dp.get_precision("Product Price")(cr)
        towrite_dict = {}
        for cost in self.browse(cr, uid, ids, context=None):
            if not cost.picking_ids:
                continue
            picking_ids = [p.id for p in cost.picking_ids]
            total_qty = 0.0
            total_cost = 0.0
            total_weight = 0.0
            total_volume = 0.0
            total_line = 0.0
            vals = self.get_valuation_lines(cr, uid, [cost.id], picking_ids=picking_ids, context=context)
            for v in vals:
                for line in cost.cost_lines:
                    v.update({"cost_id": cost.id, "cost_line_id": line.id})
                    self.pool.get("stock.valuation.adjustment.lines").create(cr, uid, v, context=context)
                total_qty += v.get("quantity", 0.0)
                total_cost += v.get("former_cost", 0.0)
                total_weight += v.get("weight", 0.0)
                total_volume += v.get("volume", 0.0)
                total_line += 1

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

                        if digits:
                            value = float_round(value, precision_digits=digits[1], rounding_method="UP")
                            value = min(value, line.price_unit - value_split)
                            value_split += value

                        if valuation.id not in towrite_dict:
                            towrite_dict[valuation.id] = value
                        else:
                            towrite_dict[valuation.id] += value
        if towrite_dict:
            for key, value in towrite_dict.items():
                line_obj.write(cr, uid, key, {"additional_landed_cost": value}, context=context)
        return True
Beispiel #47
0
class PurchaseRequestLine(models.Model):

    _name = "purchase.request.line"
    _description = "Purchase Request Line"
    _inherit = ['mail.thread', 'ir.needaction_mixin']

    @api.multi
    @api.depends('product_id', 'name', 'product_uom_id', 'product_qty',
                 'analytic_account_id', 'date_required', 'specifications')
    def _compute_is_editable(self):
        for rec in self:
            if rec.request_id.state in ('to_approve', 'approved', 'rejected'):
                rec.is_editable = False
            else:
                rec.is_editable = True

    @api.multi
    def _compute_supplier_id(self):
        for rec in self:
            if rec.product_id:
                if rec.product_id.seller_ids:
                    rec.supplier_id = rec.product_id.seller_ids[0].name

    product_id = fields.Many2one('product.product',
                                 'Product',
                                 domain=[('purchase_ok', '=', True)],
                                 track_visibility='onchange')
    name = fields.Char('Description', size=256, track_visibility='onchange')
    product_uom_id = fields.Many2one('product.uom',
                                     'Product Unit of Measure',
                                     track_visibility='onchange')
    product_qty = fields.Float(
        'Quantity',
        track_visibility='onchange',
        digits_compute=dp.get_precision('Product Unit of Measure'))
    product_price = fields.Float('Price', track_visibility='onchange')
    accepted = fields.Boolean('Accepted', track_visibility='onchange')
    request_id = fields.Many2one('purchase.request',
                                 'Purchase Request',
                                 ondelete='cascade',
                                 readonly=True)
    company_id = fields.Many2one('res.company',
                                 related='request_id.company_id',
                                 string='Company',
                                 store=True,
                                 readonly=True)
    analytic_account_id = fields.Many2one('account.analytic.account',
                                          'Analytic Account',
                                          track_visibility='onchange')
    requested_by = fields.Many2one('res.users',
                                   related='request_id.requested_by',
                                   string='Requested by',
                                   store=True,
                                   readonly=True)
    assigned_to = fields.Many2one('res.users',
                                  related='request_id.assigned_to',
                                  string='Assigned to',
                                  store=True,
                                  readonly=True)
    date_start = fields.Date(related='request_id.date_start',
                             string='Request Date',
                             readonly=True,
                             store=True)
    description = fields.Text(related='request_id.description',
                              string='Description',
                              readonly=True,
                              store=True)
    origin = fields.Char(related='request_id.origin',
                         size=32,
                         string='Source Document',
                         readonly=True,
                         store=True)
    date_required = fields.Date(string='Request Date',
                                required=True,
                                track_visibility='onchange',
                                default=fields.Date.context_today)
    is_editable = fields.Boolean(string='Is editable',
                                 compute="_compute_is_editable",
                                 readonly=True)
    specifications = fields.Text(string='Specifications')
    request_state = fields.Selection(string='Request state',
                                     readonly=True,
                                     related='request_id.state',
                                     selection=_STATES,
                                     store=True)
    supplier_id = fields.Many2one('res.partner',
                                  string='Preferred supplier',
                                  compute="_compute_supplier_id")

    procurement_id = fields.Many2one('procurement.order',
                                     'Procurement Order',
                                     readonly=True)

    attachment_ids = fields.Many2many('ir.attachment',
                                      'class_ir_attachments_rel', 'class_id',
                                      'attachment_id', 'Attachments')
    price_total = fields.Float(string='Total',
                               track_visibility='onchange',
                               compute="_compute_amount",
                               store=True)

    @api.onchange('product_id')
    def onchange_product_id(self):
        if self.product_id:
            name = self.product_id.name
            if self.product_id.code:
                name = '[%s] %s' % (name, self.product_id.code)
            if self.product_id.description_purchase:
                name += '\n' + self.product_id.description_purchase
            self.product_uom_id = self.product_id.uom_id.id
            self.product_qty = 1
            self.name = name

    @api.multi
    @api.depends('product_qty', 'product_price')
    def _compute_amount(self):
        if self.product_qty > 0:
            self.price_total = self.product_price * self.product_qty
Beispiel #48
0
 "sequence": fields.integer("Sequence"),
 "product_id": fields.many2one(
     "product.product", "Product", domain=[("is_rent", "=", True)], change_default=True
 ),
 "invoice_lines": fields.many2many(
     "account.invoice.line",
     "rent_order_line_invoice_rel",
     "order_line_id",
     "invoice_id",
     "Invoice Lines",
     readonly=True,
 ),
 "price_unit": fields.float(
     "Unit Price",
     required=True,
     digits_compute=dp.get_precision("Product Price"),
     readonly=True,
     states={"draft": [("readonly", False)]},
 ),
 "price_subtotal": fields.function(_amount_line, string="Subtotal", digits_compute=dp.get_precision("Account")),
 "tax_id": fields.many2many(
     "account.tax",
     "rent_order_tax",
     "order_line_id",
     "tax_id",
     "Taxes",
     readonly=True,
     states={"draft": [("readonly", False)]},
 ),
 "product_uom_qty": fields.float(
     "Quantity",
class wh_move_line(models.Model):
    _name = 'wh.move.line'

    _rec_name = 'note'

    MOVE_LINE_TYPE = [
        ('out', u'出库'),
        ('in', u'入库'),
        ('internal', u'内部调拨'),
    ]

    MOVE_LINE_STATE = [
        ('draft', u'草稿'),
        ('done', u'已审核'),
    ]

    ORIGIN_EXPLAIN = {
        ('wh.assembly', 'out'): u'组装单子件',
        ('wh.assembly', 'in'): u'组装单组合件',
        ('wh.disassembly', 'out'): u'拆卸单组合件',
        ('wh.disassembly', 'in'): u'拆卸单子件',
        ('wh.internal', True): u'调拨出库',
        ('wh.internal', False): u'调拨入库',
        'wh.out.inventory': u'盘亏',
        'wh.out.others': u'其他出库',
        'wh.in.inventory': u'盘盈',
        'wh.in.others': u'其他入库',
        'buy.receipt.sell': u'采购入库',
        'buy.receipt.return': u'采购退货',
        'sell.delivery.sell': u'销售出库',
        'sell.delivery.return': u'销售退货',
    }

    @api.one
    @api.depends('goods_qty', 'price_taxed', 'discount_amount', 'tax_rate')
    def _compute_all_amount(self):
        '''当订单行的数量、含税单价、折扣额、税率改变时,改变金额、税额、价税合计'''
        self.price = self.price_taxed / (1 + self.tax_rate * 0.01)
        self.amount = self.goods_qty * self.price - self.discount_amount  # 折扣后金额
        self.tax_amount = self.amount * self.tax_rate * 0.01  # 税额
        self.subtotal = self.amount + self.tax_amount

    @api.one
    @api.depends('goods_id')
    def _compute_using_attribute(self):
        self.using_attribute = self.goods_id.attribute_ids and True or False

    @api.one
    @api.depends('move_id.warehouse_id')
    def _get_line_warehouse(self):
        self.warehouse_id = self.move_id.warehouse_id.id
        if (self.move_id.origin == 'wh.assembly' or self.move_id.origin
                == 'wh.disassembly') and self.type == 'in':
            self.warehouse_id = self.env.ref(
                'warehouse.warehouse_production').id

    @api.one
    @api.depends('move_id.warehouse_dest_id')
    def _get_line_warehouse_dest(self):
        self.warehouse_dest_id = self.move_id.warehouse_dest_id.id
        if (self.move_id.origin == 'wh.assembly' or self.move_id.origin
                == 'wh.disassembly') and self.type == 'out':
            self.warehouse_dest_id = self.env.ref(
                'warehouse.warehouse_production').id

    move_id = fields.Many2one('wh.move',
                              string=u'移库单',
                              ondelete='cascade',
                              help=u'出库/入库/移库单行对应的移库单')
    date = fields.Date(u'完成日期', copy=False, help=u'单据完成日期')
    cost_time = fields.Datetime(u'审核时间', copy=False, help=u'单据审核时间')
    type = fields.Selection(MOVE_LINE_TYPE,
                            u'类型',
                            default=lambda self: self.env.context.get('type'),
                            help=u'类型:出库、入库 或者 内部调拨')
    state = fields.Selection(MOVE_LINE_STATE,
                             u'状态',
                             copy=False,
                             default='draft',
                             help=u'状态标识,新建时状态为草稿;审核后状态为已审核')
    goods_id = fields.Many2one('goods',
                               string=u'产品',
                               required=True,
                               index=True,
                               ondelete='restrict',
                               help=u'该单据行对应的产品')
    using_attribute = fields.Boolean(compute='_compute_using_attribute',
                                     string=u'使用属性',
                                     help=u'该单据行对应的产品是否存在属性,存在True否则False')
    attribute_id = fields.Many2one('attribute',
                                   u'属性',
                                   ondelete='restrict',
                                   help=u'该单据行对应的产品的属性')
    using_batch = fields.Boolean(related='goods_id.using_batch',
                                 string=u'批号管理',
                                 help=u'该单据行对应的产品是否使用批号管理')
    force_batch_one = fields.Boolean(related='goods_id.force_batch_one',
                                     string=u'每批号数量为1',
                                     help=u'该单据行对应的产品是否每批号数量为1,是True否则False')
    lot = fields.Char(u'批号', help=u'该单据行对应的产品的批号,一般是入库单行')
    lot_id = fields.Many2one('wh.move.line',
                             u'批号',
                             help=u'该单据行对应的产品的批号,一般是出库单行')
    lot_qty = fields.Float(related='lot_id.qty_remaining',
                           string=u'批号数量',
                           digits=dp.get_precision('Quantity'),
                           help=u'该单据行对应的产品批号的商品剩余数量')
    lot_uos_qty = fields.Float(u'批号辅助数量',
                               digits=dp.get_precision('Quantity'),
                               help=u'该单据行对应的产品的批号辅助数量')
    production_date = fields.Date(u'生产日期',
                                  default=fields.Date.context_today,
                                  help=u'产品的生产日期')
    shelf_life = fields.Integer(u'保质期(天)', help=u'产品的保质期(天)')
    valid_date = fields.Date(u'有效期至', help=u'产品的有效期')
    uom_id = fields.Many2one('uom',
                             string=u'单位',
                             ondelete='restrict',
                             help=u'产品的计量单位')
    uos_id = fields.Many2one('uom',
                             string=u'辅助单位',
                             ondelete='restrict',
                             help=u'产品的辅助单位')
    warehouse_id = fields.Many2one('warehouse',
                                   u'调出仓库',
                                   ondelete='restrict',
                                   store=True,
                                   compute=_get_line_warehouse,
                                   help=u'单据的来源仓库')
    warehouse_dest_id = fields.Many2one('warehouse',
                                        u'调入仓库',
                                        ondelete='restrict',
                                        store=True,
                                        compute=_get_line_warehouse_dest,
                                        help=u'单据的目的仓库')
    goods_qty = fields.Float(u'数量',
                             digits=dp.get_precision('Quantity'),
                             default=1,
                             help=u'产品的数量')
    goods_uos_qty = fields.Float(u'辅助数量',
                                 digits=dp.get_precision('Quantity'),
                                 default=1,
                                 help=u'产品的辅助数量')
    price = fields.Float(u'单价',
                         compute=_compute_all_amount,
                         store=True,
                         readonly=True,
                         digits=dp.get_precision('Amount'),
                         help=u'产品的单价')
    price_taxed = fields.Float(u'含税单价',
                               digits=dp.get_precision('Amount'),
                               help=u'产品的含税单价')
    discount_rate = fields.Float(u'折扣率%', help=u'单据的折扣率%')
    discount_amount = fields.Float(u'折扣额',
                                   digits=dp.get_precision('Amount'),
                                   help=u'单据的折扣额')
    amount = fields.Float(u'金额',
                          compute=_compute_all_amount,
                          store=True,
                          readonly=True,
                          digits=dp.get_precision('Amount'),
                          help=u'单据的金额,计算得来')
    tax_rate = fields.Float(u'税率(%)', help=u'单据的税率(%)')
    tax_amount = fields.Float(u'税额',
                              compute=_compute_all_amount,
                              store=True,
                              readonly=True,
                              digits=dp.get_precision('Amount'),
                              help=u'单据的税额,有单价×数量×税率计算得来')
    subtotal = fields.Float(u'价税合计',
                            compute=_compute_all_amount,
                            store=True,
                            readonly=True,
                            digits=dp.get_precision('Amount'),
                            help=u'价税合计,有不含税金额+税额计算得来')
    note = fields.Text(u'备注', help=u'可以为该单据添加一些需要的标识信息')
    cost_unit = fields.Float(u'单位成本',
                             digits=dp.get_precision('Amount'),
                             help=u'入库/出库单位成本')
    cost = fields.Float(u'成本',
                        compute='_compute_cost',
                        inverse='_inverse_cost',
                        digits=dp.get_precision('Amount'),
                        store=True,
                        help=u'入库/出库成本')

    @api.one
    @api.depends('cost_unit', 'goods_qty')
    def _compute_cost(self):
        self.cost = self.cost_unit * self.goods_qty

    @api.one
    def _inverse_cost(self):
        self.cost_unit = safe_division(self.cost, self.goods_qty)

    def get_origin_explain(self):
        self.ensure_one()
        if self.move_id.origin in ('wh.assembly', 'wh.disassembly'):
            return self.ORIGIN_EXPLAIN.get((self.move_id.origin, self.type))
        elif self.move_id.origin == 'wh.internal':
            return self.ORIGIN_EXPLAIN.get(
                (self.move_id.origin,
                 self.env.context.get('internal_out', False)))
        elif self.move_id.origin in self.ORIGIN_EXPLAIN.keys():
            return self.ORIGIN_EXPLAIN.get(self.move_id.origin)

        return ''

    @api.model
    def default_get(self, fields):
        res = super(wh_move_line, self).default_get(fields)
        if self.env.context.get('goods_id') and self.env.context.get(
                'warehouse_id'):
            res.update({
                'goods_id': self.env.context.get('goods_id'),
                'warehouse_id': self.env.context.get('warehouse_id')
            })

        return res

    def get_real_cost_unit(self):
        self.ensure_one()
        return safe_division(self.cost, self.goods_qty)

    @api.multi
    def name_get(self):
        res = []
        for line in self:
            if self.env.context.get('match'):
                res.append((line.id, '%s-%s->%s(%s, %s%s)' %
                            (line.move_id.name, line.warehouse_id.name,
                             line.warehouse_dest_id.name, line.goods_id.name,
                             str(line.goods_qty), line.uom_id.name)))
            else:
                res.append((line.id, line.lot))
        return res

    @api.model
    def name_search(self, name='', args=None, operator='ilike', limit=100):
        ''' 批号下拉的时候显示批次和剩余数量 '''
        result = []
        domain = []
        if args:
            domain = args
        if name:
            domain.append(('lot', operator, name))
        records = self.search(domain, limit=limit)
        for line in records:
            result.append(
                (line.id, u'%s %s 余 %s' %
                 (line.lot, line.warehouse_dest_id.name, line.qty_remaining)))
        return result

    def check_availability(self):
        if self.warehouse_dest_id == self.warehouse_id:
            raise osv.except_osv(u'错误', u'调出仓库不可以和调入仓库一样')

    def prev_action_done(self):
        pass

    @api.multi
    def action_done(self):
        for line in self:
            line.check_availability()
            line.prev_action_done()
            line.write({
                'state': 'done',
                'date': line.move_id.date,
                'cost_time': fields.Datetime.now(self),
            })

    def check_cancel(self):
        pass

    def prev_action_cancel(self):
        pass

    @api.multi
    def action_cancel(self):
        for line in self:
            line.check_cancel()
            line.prev_action_cancel()
            line.write({
                'state': 'draft',
                'date': False,
            })

    @api.one
    def compute_lot_compatible(self):
        if self.warehouse_id and self.lot_id and self.lot_id.warehouse_dest_id != self.warehouse_id:
            self.lot_id = False

        if self.goods_id and self.lot_id and self.lot_id.goods_id != self.goods_id:
            self.lot_id = False

    def compute_lot_domain(self):
        lot_domain = [('goods_id', '=', self.goods_id.id),
                      ('state', '=', 'done'), ('lot', '!=', False),
                      ('qty_remaining', '>', 0)]

        if self.move_id:
            lot_domain.append(
                ('warehouse_dest_id', '=', self.move_id.warehouse_id.id))

        if self.attribute_id:
            lot_domain.append(('attribute_id', '=', self.attribute_id.id))

        return lot_domain

    @api.one
    def compute_suggested_cost(self):
        if self.env.context.get(
                'type'
        ) == 'out' and self.goods_id and self.warehouse_id and self.goods_qty:
            cost, cost_unit = self.goods_id.get_suggested_cost_by_warehouse(
                self.warehouse_id, self.goods_qty, self.lot_id,
                self.attribute_id)

            self.cost_unit = cost_unit
            self.cost = cost

    @api.multi
    @api.onchange('goods_id')
    def onchange_goods_id(self):
        if self.goods_id:
            self.uom_id = self.goods_id.uom_id
            self.uos_id = self.goods_id.uos_id
            self.attribute_id = False
            self.cost_unit = self.goods_id.cost
            if self.goods_id.using_batch and self.goods_id.force_batch_one:
                self.goods_qty = 1
                self.goods_uos_qty = self.goods_id.anti_conversion_unit(
                    self.goods_qty)
            else:
                self.goods_qty = self.goods_id.conversion_unit(
                    self.goods_uos_qty or 1)

        self.compute_suggested_cost()
        self.compute_lot_compatible()

        return {'domain': {'lot_id': self.compute_lot_domain()}}

    @api.multi
    @api.onchange('warehouse_id')
    def onchange_warehouse_id(self):
        self.compute_suggested_cost()
        self.compute_lot_domain()
        self.compute_lot_compatible()

        return {'domain': {'lot_id': self.compute_lot_domain()}}

    @api.multi
    @api.onchange('attribute_id')
    def onchange_attribute_id(self):
        self.compute_suggested_cost()
        return {'domain': {'lot_id': self.compute_lot_domain()}}

    @api.one
    @api.onchange('goods_qty')
    def onchange_goods_qty(self):
        self.compute_suggested_cost()

    @api.one
    @api.onchange('goods_uos_qty')
    def onchange_goods_uos_qty(self):
        if self.goods_id:
            self.goods_qty = self.goods_id.conversion_unit(self.goods_uos_qty)
        self.compute_suggested_cost()

    @api.one
    @api.onchange('lot_id')
    def onchange_lot_id(self):
        if self.lot_id:
            self.lot_qty = self.lot_id.qty_remaining
            self.lot_uos_qty = self.goods_id.anti_conversion_unit(self.lot_qty)

            if self.env.context.get('type') == 'internal':
                self.lot = self.lot_id.lot

    @api.one
    @api.onchange('goods_qty', 'price_taxed', 'discount_rate')
    def onchange_discount_rate(self):
        '''当数量、单价或优惠率发生变化时,优惠金额发生变化'''
        price = self.price_taxed / (1 + self.tax_rate * 0.01)
        self.discount_amount = self.goods_qty * price * self.discount_rate * 0.01

    @api.multi
    def unlink(self):
        for line in self:
            if line.state == 'done':
                raise osv.except_osv(u'错误', u'不可以删除已经完成的明细')

        return super(wh_move_line, self).unlink()
Beispiel #50
0
    def compute_landed_cost(self, cr, uid, ids, context=None):
        line_obj = self.pool.get('stock.valuation.adjustment.lines')
        unlink_ids = line_obj.search(cr, uid, [('cost_id', 'in', ids)], context=context)
        line_obj.unlink(cr, uid, unlink_ids, context=context)
        digits = dp.get_precision('Product Price')(cr)
        towrite_dict = {}
        for cost in self.browse(cr, uid, ids, context=None):
            if not cost.picking_ids:
                continue
            picking_ids = [p.id for p in cost.picking_ids]
            total_qty = 0.0
            total_cost = 0.0
            total_weight = 0.0
            total_volume = 0.0
            total_line = 0.0
            vals = self.get_valuation_lines(cr, uid, [cost.id], picking_ids=picking_ids, context=context)
            for v in vals:
                for line in cost.cost_lines:
                    v.update({'cost_id': cost.id, 'cost_line_id': line.id})
                    self.pool.get('stock.valuation.adjustment.lines').create(cr, uid, v, context=context)
                total_qty += v.get('quantity', 0.0)
                total_cost += v.get('former_cost', 0.0)
                total_weight += v.get('weight', 0.0)
                total_volume += v.get('volume', 0.0)
                total_line += 1

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

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

                        if valuation.id not in towrite_dict:
                            towrite_dict[valuation.id] = value
                        else:
                            towrite_dict[valuation.id] += value
        if towrite_dict:
            for key, value in towrite_dict.items():
                line_obj.write(cr, uid, key, {'additional_landed_cost': value}, context=context)
        return True
    
    def _get_uom_id(self, cr, uid, context=None):
        try:
            proxy = self.pool.get('ir.model.data')
            result = proxy.get_object_reference(cr, uid, 'product', 'product_uom_unit')
            return result[1]
        except Exception, ex:
            return False
    
    _columns = {
        
#        'location_destination_id': fields.many2one('stock.location', 'Stock Destination Location'),
#        'location_id': fields.many2one('stock.location', 'Stock Source Location'),
        'product_id': fields.many2one('product.product', 'Product'),
        'back_order_id': fields.many2one('back.to.back.order', 'Back Order'),
        'qty': fields.float('Quantity'),
        'price': fields.float('Unit Price'),
        'subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')),
        'taxes_id': fields.many2many('account.tax', 'purchase_order_taxe', 'ord_id', 'tax_id', 'Taxes'),
        'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True),
        
           
    }
    
    
    _defaults = {
        'product_uom' : _get_uom_id,
    }

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: