[MERGE] forward port branch saas-11 up to ba6ca78
This commit is contained in:
@@ -1083,10 +1083,13 @@ class AccountMoveLine(models.Model):
|
|||||||
# the provided values were not already multi-currency
|
# the provided values were not already multi-currency
|
||||||
if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id:
|
if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id:
|
||||||
vals['currency_id'] = account.currency_id.id
|
vals['currency_id'] = account.currency_id.id
|
||||||
ctx = {}
|
if self._context.get('skip_full_reconcile_check') == 'amount_currency_excluded':
|
||||||
if 'date' in vals:
|
vals['amount_currency'] = 0.0
|
||||||
ctx['date'] = vals['date']
|
else:
|
||||||
vals['amount_currency'] = account.company_id.currency_id.with_context(ctx).compute(amount, account.currency_id)
|
ctx = {}
|
||||||
|
if 'date' in vals:
|
||||||
|
ctx['date'] = vals['date']
|
||||||
|
vals['amount_currency'] = account.company_id.currency_id.with_context(ctx).compute(amount, account.currency_id)
|
||||||
if not ok:
|
if not ok:
|
||||||
raise UserError(_('You cannot use this general account in this journal, check the tab \'Entry Controls\' on the related journal.'))
|
raise UserError(_('You cannot use this general account in this journal, check the tab \'Entry Controls\' on the related journal.'))
|
||||||
|
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ class AccountAssetAsset(models.Model):
|
|||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_entries(self, date, group_entries=False):
|
def _compute_entries(self, date, group_entries=False):
|
||||||
depreciation_ids = self.env['account.asset.depreciation.line'].with_context(depreciation_date=date).search([
|
depreciation_ids = self.env['account.asset.depreciation.line'].search([
|
||||||
('asset_id', 'in', self.ids), ('depreciation_date', '<=', date),
|
('asset_id', 'in', self.ids), ('depreciation_date', '<=', date),
|
||||||
('move_check', '=', False)])
|
('move_check', '=', False)])
|
||||||
if group_entries:
|
if group_entries:
|
||||||
|
|||||||
@@ -460,6 +460,7 @@ msgstr ""
|
|||||||
|
|
||||||
#. module: account_asset
|
#. module: account_asset
|
||||||
#: model:ir.model.fields,field_description:account_asset.field_account_asset_category_account_depreciation_id
|
#: model:ir.model.fields,field_description:account_asset.field_account_asset_category_account_depreciation_id
|
||||||
|
#: model:ir.ui.view,arch_db:account_asset.view_account_asset_asset_form
|
||||||
msgid "Depreciation Entries: Asset Account"
|
msgid "Depreciation Entries: Asset Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<field name="account_asset_id" nolabel="1" attrs="{'invisible': [('type','=', False)]}"/>
|
<field name="account_asset_id" nolabel="1" attrs="{'invisible': [('type','=', False)]}"/>
|
||||||
<div>
|
<div>
|
||||||
<label for="account_depreciation_id" string="Depreciation Expense Account" attrs="{'invisible': [('type','!=','purchase')]}"/>
|
<label for="account_depreciation_id" string="Depreciation Entries: Asset Account" attrs="{'invisible': [('type','!=','purchase')]}"/>
|
||||||
<label for="account_depreciation_id" string="Recognition Account" attrs="{'invisible': [('type','!=','sale')]}"/>
|
<label for="account_depreciation_id" string="Recognition Account" attrs="{'invisible': [('type','!=','sale')]}"/>
|
||||||
</div>
|
</div>
|
||||||
<field name="account_depreciation_id" nolabel="1"/>
|
<field name="account_depreciation_id" nolabel="1"/>
|
||||||
|
|||||||
@@ -425,6 +425,8 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
|||||||
anonymized_value = '2011-11-11 11:11:11'
|
anonymized_value = '2011-11-11 11:11:11'
|
||||||
elif field_type == 'float':
|
elif field_type == 'float':
|
||||||
anonymized_value = 0.0
|
anonymized_value = 0.0
|
||||||
|
elif field_type == 'monetary':
|
||||||
|
anonymized_value = 0.0
|
||||||
elif field_type == 'integer':
|
elif field_type == 'integer':
|
||||||
anonymized_value = 0
|
anonymized_value = 0
|
||||||
elif field_type in ['binary', 'many2many', 'many2one', 'one2many', 'reference']: # cannot anonymize these kind of fields
|
elif field_type in ['binary', 'many2many', 'many2one', 'one2many', 'reference']: # cannot anonymize these kind of fields
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ anonymization_field_purchase_order_amount_tax,purchase.order,amount_tax
|
|||||||
anonymization_field_purchase_order_amount_untaxed,purchase.order,amount_untaxed
|
anonymization_field_purchase_order_amount_untaxed,purchase.order,amount_untaxed
|
||||||
anonymization_field_purchase_order_line_price_unit,purchase.order.line,price_unit
|
anonymization_field_purchase_order_line_price_unit,purchase.order.line,price_unit
|
||||||
anonymization_field_account_invoice_tax_amount,account.invoice.tax,amount
|
anonymization_field_account_invoice_tax_amount,account.invoice.tax,amount
|
||||||
anonymization_field_account_invoice_tax_base,account.invoice.tax,base
|
|
||||||
anonymization_field_product_name,product.template,name
|
anonymization_field_product_name,product.template,name
|
||||||
anonymization_field_res_users_signature,res.users,signature
|
anonymization_field_res_users_signature,res.users,signature
|
||||||
anonymization_field_res_partner_contact_name,res.partner.contact,name
|
anonymization_field_res_partner_contact_name,res.partner.contact,name
|
||||||
|
|||||||
|
@@ -81,7 +81,7 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
|
|||||||
if (this.last_scanned_barcode) {
|
if (this.last_scanned_barcode) {
|
||||||
var new_qty = window.prompt(_t('Set quantity'), character) || "0";
|
var new_qty = window.prompt(_t('Set quantity'), character) || "0";
|
||||||
new_qty = new_qty.replace(',', '.');
|
new_qty = new_qty.replace(',', '.');
|
||||||
var record = this._get_records(field).find(function(record) {
|
var record = _.find(this._get_records(field), function (record) {
|
||||||
return record.get('product_barcode') === self.last_scanned_barcode;
|
return record.get('product_barcode') === self.last_scanned_barcode;
|
||||||
});
|
});
|
||||||
if (record) {
|
if (record) {
|
||||||
@@ -159,8 +159,13 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_get_records: function(field) {
|
_get_records: function(field) {
|
||||||
return field.viewmanager.active_view.controller.records || // tree view
|
var active_view = field.viewmanager.active_view;
|
||||||
field.viewmanager.active_view.controller.widgets; // kanban view
|
if (active_view.type === "kanban") {
|
||||||
|
return active_view.controller.widgets;
|
||||||
|
} else {
|
||||||
|
// tree view case
|
||||||
|
return active_view.controller.records.records;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -527,7 +527,7 @@
|
|||||||
<field name="source_id" invisible="1"/>
|
<field name="source_id" invisible="1"/>
|
||||||
<field name="stage_id"/>
|
<field name="stage_id"/>
|
||||||
<field name="planned_revenue" sum="Expected Revenues"/>
|
<field name="planned_revenue" sum="Expected Revenues"/>
|
||||||
<field name="probability" />
|
<field name="probability" avg="Avg. of Probability"/>
|
||||||
<field name="team_id"/>
|
<field name="team_id"/>
|
||||||
<field name="user_id"/>
|
<field name="user_id"/>
|
||||||
<field name="referred" invisible="1"/>
|
<field name="referred" invisible="1"/>
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ class HrExpense(models.Model):
|
|||||||
'product_id': line.get('product_id'),
|
'product_id': line.get('product_id'),
|
||||||
'product_uom_id': line.get('uom_id'),
|
'product_uom_id': line.get('uom_id'),
|
||||||
'analytic_account_id': line.get('analytic_account_id'),
|
'analytic_account_id': line.get('analytic_account_id'),
|
||||||
|
'payment_id': line.get('payment_id'),
|
||||||
}
|
}
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -195,11 +196,29 @@ class HrExpense(models.Model):
|
|||||||
move_lines = expense._move_line_get()
|
move_lines = expense._move_line_get()
|
||||||
|
|
||||||
#create one more move line, a counterline for the total on payable account
|
#create one more move line, a counterline for the total on payable account
|
||||||
|
payment_id = False
|
||||||
total, total_currency, move_lines = expense._compute_expense_totals(company_currency, move_lines, acc_date)
|
total, total_currency, move_lines = expense._compute_expense_totals(company_currency, move_lines, acc_date)
|
||||||
if expense.payment_mode == 'company_account':
|
if expense.payment_mode == 'company_account':
|
||||||
if not expense.sheet_id.bank_journal_id.default_credit_account_id:
|
if not expense.sheet_id.bank_journal_id.default_credit_account_id:
|
||||||
raise UserError(_("No credit account found for the %s journal, please configure one.") % (expense.sheet_id.bank_journal_id.name))
|
raise UserError(_("No credit account found for the %s journal, please configure one.") % (expense.sheet_id.bank_journal_id.name))
|
||||||
emp_account = expense.sheet_id.bank_journal_id.default_credit_account_id.id
|
emp_account = expense.sheet_id.bank_journal_id.default_credit_account_id.id
|
||||||
|
journal = expense.bank_journal_id
|
||||||
|
#create payment
|
||||||
|
payment_methods = (total < 0) and journal.outbound_payment_method_ids or journal.inbound_payment_method_ids
|
||||||
|
journal_currency = journal.currency_id or journal.company_id.currency_id
|
||||||
|
payment = self.env['account.payment'].create({
|
||||||
|
'payment_method_id': payment_methods and payment_methods[0].id or False,
|
||||||
|
'payment_type': total < 0 and 'outbound' or 'inbound',
|
||||||
|
'partner_id': expense.employee_id.address_home_id.commercial_partner_id.id,
|
||||||
|
'partner_type': 'supplier',
|
||||||
|
'journal_id': journal.id,
|
||||||
|
'payment_date': expense.date,
|
||||||
|
'state': 'reconciled',
|
||||||
|
'currency_id': diff_currency_p and expense.currency_id.id or journal_currency.id,
|
||||||
|
'amount': diff_currency_p and abs(total_currency) or abs(total),
|
||||||
|
'name': expense.name,
|
||||||
|
})
|
||||||
|
payment_id = payment.id
|
||||||
else:
|
else:
|
||||||
if not expense.employee_id.address_home_id:
|
if not expense.employee_id.address_home_id:
|
||||||
raise UserError(_("No Home Address found for the employee %s, please configure one.") % (expense.employee_id.name))
|
raise UserError(_("No Home Address found for the employee %s, please configure one.") % (expense.employee_id.name))
|
||||||
@@ -213,7 +232,8 @@ class HrExpense(models.Model):
|
|||||||
'date_maturity': acc_date,
|
'date_maturity': acc_date,
|
||||||
'amount_currency': diff_currency_p and total_currency or False,
|
'amount_currency': diff_currency_p and total_currency or False,
|
||||||
'currency_id': diff_currency_p and expense.currency_id.id or False,
|
'currency_id': diff_currency_p and expense.currency_id.id or False,
|
||||||
'ref': expense.employee_id.address_home_id.ref or False
|
'ref': expense.employee_id.address_home_id.ref or False,
|
||||||
|
'payment_id': payment_id,
|
||||||
})
|
})
|
||||||
|
|
||||||
#convert eml into an osv-valid format
|
#convert eml into an osv-valid format
|
||||||
|
|||||||
@@ -464,7 +464,7 @@
|
|||||||
<field name="account_id" ref="p11235"/>
|
<field name="account_id" ref="p11235"/>
|
||||||
<field name="refund_account_id" ref="p20011"/>
|
<field name="refund_account_id" ref="p20011"/>
|
||||||
<field name="chart_template_id" ref="indian_chart_template_standard"/>
|
<field name="chart_template_id" ref="indian_chart_template_standard"/>
|
||||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_70'), ref('st_tag_in_21')])]"/>
|
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_21'), ref('st_tag_in_66')])]"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="input_tax_12" model="account.tax.template">
|
<record id="input_tax_12" model="account.tax.template">
|
||||||
<field name="name">(standard)Input Sales Tax @ 12%</field>
|
<field name="name">(standard)Input Sales Tax @ 12%</field>
|
||||||
@@ -476,7 +476,7 @@
|
|||||||
<field name="account_id" ref="p11235"/>
|
<field name="account_id" ref="p11235"/>
|
||||||
<field name="refund_account_id" ref="p20011"/>
|
<field name="refund_account_id" ref="p20011"/>
|
||||||
<field name="chart_template_id" ref="indian_chart_template_standard"/>
|
<field name="chart_template_id" ref="indian_chart_template_standard"/>
|
||||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_56')])]"/>
|
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_18'), ref('st_tag_in_63')])]"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="input_tax_4" model="account.tax.template">
|
<record id="input_tax_4" model="account.tax.template">
|
||||||
<field name="name">(standard)Input Sales Tax @ 4%</field>
|
<field name="name">(standard)Input Sales Tax @ 4%</field>
|
||||||
@@ -488,7 +488,7 @@
|
|||||||
<field name="account_id" ref="p11235"/>
|
<field name="account_id" ref="p11235"/>
|
||||||
<field name="refund_account_id" ref="p20011"/>
|
<field name="refund_account_id" ref="p20011"/>
|
||||||
<field name="chart_template_id" ref="indian_chart_template_standard"/>
|
<field name="chart_template_id" ref="indian_chart_template_standard"/>
|
||||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_15'), ref('st_tag_in_70')])]"/>
|
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_15'), ref('st_tag_in_60')])]"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="add_input_vat_1" model="account.tax.template">
|
<record id="add_input_vat_1" model="account.tax.template">
|
||||||
<field name="name">(standard)Additional Input VAT @ 1%</field>
|
<field name="name">(standard)Additional Input VAT @ 1%</field>
|
||||||
@@ -607,7 +607,7 @@
|
|||||||
<field name="account_id" ref="p112341"/>
|
<field name="account_id" ref="p112341"/>
|
||||||
<field name="refund_account_id" ref="p20011"/>
|
<field name="refund_account_id" ref="p20011"/>
|
||||||
<field name="chart_template_id" ref="indian_chart_template_standard"/>
|
<field name="chart_template_id" ref="indian_chart_template_standard"/>
|
||||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_25')])]"/>
|
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_25'), ref('st_tag_in_63')])]"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="sale_edu_cess_service_tax_2" model="account.tax.template">
|
<record id="sale_edu_cess_service_tax_2" model="account.tax.template">
|
||||||
<field name="name">(standard)Input Education Cess @ 2% On Service Tax</field>
|
<field name="name">(standard)Input Education Cess @ 2% On Service Tax</field>
|
||||||
|
|||||||
+30
-25
@@ -30,6 +30,35 @@ class AccountInvoice(models.Model):
|
|||||||
]}
|
]}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _prepare_invoice_line_from_po_line(self, line):
|
||||||
|
if line.product_id.purchase_method == 'purchase':
|
||||||
|
qty = line.product_qty - line.qty_invoiced
|
||||||
|
else:
|
||||||
|
qty = line.qty_received - line.qty_invoiced
|
||||||
|
if float_compare(qty, 0.0, precision_rounding=line.product_uom.rounding) <= 0:
|
||||||
|
qty = 0.0
|
||||||
|
taxes = line.taxes_id
|
||||||
|
invoice_line_tax_ids = self.purchase_id.fiscal_position_id.map_tax(taxes)
|
||||||
|
invoice_line = self.env['account.invoice.line']
|
||||||
|
data = {
|
||||||
|
'purchase_line_id': line.id,
|
||||||
|
'name': self.purchase_id.name+': '+line.name,
|
||||||
|
'origin': self.purchase_id.origin,
|
||||||
|
'uom_id': line.product_uom.id,
|
||||||
|
'product_id': line.product_id.id,
|
||||||
|
'account_id': invoice_line.with_context({'journal_id': self.journal_id.id, 'type': 'in_invoice'})._default_account(),
|
||||||
|
'price_unit': line.order_id.currency_id.compute(line.price_unit, self.currency_id, round=False),
|
||||||
|
'quantity': qty,
|
||||||
|
'discount': 0.0,
|
||||||
|
'account_analytic_id': line.account_analytic_id.id,
|
||||||
|
'analytic_tag_ids': line.analytic_tag_ids.ids,
|
||||||
|
'invoice_line_tax_ids': invoice_line_tax_ids.ids
|
||||||
|
}
|
||||||
|
account = invoice_line.get_invoice_line_account('in_invoice', line.product_id, self.purchase_id.fiscal_position_id, self.env.user.company_id)
|
||||||
|
if account:
|
||||||
|
data['account_id'] = account.id
|
||||||
|
return data
|
||||||
|
|
||||||
# Load all unsold PO lines
|
# Load all unsold PO lines
|
||||||
@api.onchange('purchase_id')
|
@api.onchange('purchase_id')
|
||||||
def purchase_order_change(self):
|
def purchase_order_change(self):
|
||||||
@@ -43,31 +72,7 @@ class AccountInvoice(models.Model):
|
|||||||
# Load a PO line only once
|
# Load a PO line only once
|
||||||
if line in self.invoice_line_ids.mapped('purchase_line_id'):
|
if line in self.invoice_line_ids.mapped('purchase_line_id'):
|
||||||
continue
|
continue
|
||||||
if line.product_id.purchase_method == 'purchase':
|
data = self._prepare_invoice_line_from_po_line(line)
|
||||||
qty = line.product_qty - line.qty_invoiced
|
|
||||||
else:
|
|
||||||
qty = line.qty_received - line.qty_invoiced
|
|
||||||
if float_compare(qty, 0.0, precision_rounding=line.product_uom.rounding) <= 0:
|
|
||||||
qty = 0.0
|
|
||||||
taxes = line.taxes_id
|
|
||||||
invoice_line_tax_ids = self.purchase_id.fiscal_position_id.map_tax(taxes)
|
|
||||||
data = {
|
|
||||||
'purchase_line_id': line.id,
|
|
||||||
'name': self.purchase_id.name+': '+line.name,
|
|
||||||
'origin': self.purchase_id.origin,
|
|
||||||
'uom_id': line.product_uom.id,
|
|
||||||
'product_id': line.product_id.id,
|
|
||||||
'account_id': self.env['account.invoice.line'].with_context({'journal_id': self.journal_id.id, 'type': 'in_invoice'})._default_account(),
|
|
||||||
'price_unit': line.order_id.currency_id.compute(line.price_unit, self.currency_id, round=False),
|
|
||||||
'quantity': qty,
|
|
||||||
'discount': 0.0,
|
|
||||||
'account_analytic_id': line.account_analytic_id.id,
|
|
||||||
'analytic_tag_ids': line.analytic_tag_ids.ids,
|
|
||||||
'invoice_line_tax_ids': invoice_line_tax_ids.ids
|
|
||||||
}
|
|
||||||
account = new_lines.get_invoice_line_account('in_invoice', line.product_id, self.purchase_id.fiscal_position_id, self.env.user.company_id)
|
|
||||||
if account:
|
|
||||||
data['account_id'] = account.id
|
|
||||||
new_line = new_lines.new(data)
|
new_line = new_lines.new(data)
|
||||||
new_line._set_additional_fields(self)
|
new_line._set_additional_fields(self)
|
||||||
new_lines += new_line
|
new_lines += new_line
|
||||||
|
|||||||
@@ -81,6 +81,10 @@ class SaleAdvancePaymentInv(models.TransientModel):
|
|||||||
else:
|
else:
|
||||||
amount = self.amount
|
amount = self.amount
|
||||||
name = _('Down Payment')
|
name = _('Down Payment')
|
||||||
|
if order.fiscal_position_id and self.product_id.taxes_id:
|
||||||
|
tax_ids = order.fiscal_position_id.map_tax(self.product_id.taxes_id).ids
|
||||||
|
else:
|
||||||
|
tax_ids = self.product_id.taxes_id.ids
|
||||||
|
|
||||||
invoice = inv_obj.create({
|
invoice = inv_obj.create({
|
||||||
'name': order.client_order_ref or order.name,
|
'name': order.client_order_ref or order.name,
|
||||||
@@ -100,7 +104,7 @@ class SaleAdvancePaymentInv(models.TransientModel):
|
|||||||
'uom_id': self.product_id.uom_id.id,
|
'uom_id': self.product_id.uom_id.id,
|
||||||
'product_id': self.product_id.id,
|
'product_id': self.product_id.id,
|
||||||
'sale_line_ids': [(6, 0, [so_line.id])],
|
'sale_line_ids': [(6, 0, [so_line.id])],
|
||||||
'invoice_line_tax_ids': [(6, 0, [x.id for x in self.product_id.taxes_id])],
|
'invoice_line_tax_ids': [(6, 0, tax_ids)],
|
||||||
'account_analytic_id': order.project_id.id or False,
|
'account_analytic_id': order.project_id.id or False,
|
||||||
})],
|
})],
|
||||||
'currency_id': order.pricelist_id.currency_id.id,
|
'currency_id': order.pricelist_id.currency_id.id,
|
||||||
@@ -140,6 +144,10 @@ class SaleAdvancePaymentInv(models.TransientModel):
|
|||||||
raise UserError(_('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.'))
|
raise UserError(_('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.'))
|
||||||
if self.product_id.type != 'service':
|
if self.product_id.type != 'service':
|
||||||
raise UserError(_("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product."))
|
raise UserError(_("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product."))
|
||||||
|
if order.fiscal_position_id and self.product_id.taxes_id:
|
||||||
|
tax_ids = order.fiscal_position_id.map_tax(self.product_id.taxes_id).ids
|
||||||
|
else:
|
||||||
|
tax_ids = self.product_id.taxes_id.ids
|
||||||
so_line = sale_line_obj.create({
|
so_line = sale_line_obj.create({
|
||||||
'name': _('Advance: %s') % (time.strftime('%m %Y'),),
|
'name': _('Advance: %s') % (time.strftime('%m %Y'),),
|
||||||
'price_unit': amount,
|
'price_unit': amount,
|
||||||
@@ -148,7 +156,7 @@ class SaleAdvancePaymentInv(models.TransientModel):
|
|||||||
'discount': 0.0,
|
'discount': 0.0,
|
||||||
'product_uom': self.product_id.uom_id.id,
|
'product_uom': self.product_id.uom_id.id,
|
||||||
'product_id': self.product_id.id,
|
'product_id': self.product_id.id,
|
||||||
'tax_id': [(6, 0, self.product_id.taxes_id.ids)],
|
'tax_id': [(6, 0, tax_ids)],
|
||||||
})
|
})
|
||||||
self._create_invoice(order, so_line, amount)
|
self._create_invoice(order, so_line, amount)
|
||||||
if self._context.get('open_invoices', False):
|
if self._context.get('open_invoices', False):
|
||||||
|
|||||||
@@ -91,14 +91,12 @@ class Inventory(models.Model):
|
|||||||
('category', _('One product category')),
|
('category', _('One product category')),
|
||||||
('product', _('One product only')),
|
('product', _('One product only')),
|
||||||
('partial', _('Select products manually'))]
|
('partial', _('Select products manually'))]
|
||||||
stock_settings = self.env['stock.config.settings'].search([], limit=1, order='id DESC')
|
|
||||||
if not stock_settings:
|
if self.user_has_groups('stock.group_tracking_owner'):
|
||||||
return res_filter
|
|
||||||
if stock_settings.group_stock_tracking_owner:
|
|
||||||
res_filter += [('owner', _('One owner only')), ('product_owner', _('One product for a specific owner'))]
|
res_filter += [('owner', _('One owner only')), ('product_owner', _('One product for a specific owner'))]
|
||||||
if stock_settings.group_stock_production_lot:
|
if self.user_has_groups('stock.group_production_lot'):
|
||||||
res_filter.append(('lot', _('One Lot/Serial Number')))
|
res_filter.append(('lot', _('One Lot/Serial Number')))
|
||||||
if stock_settings.group_stock_tracking_lot:
|
if self.user_has_groups('stock.group_tracking_lot'):
|
||||||
res_filter.append(('pack', _('A Pack')))
|
res_filter.append(('pack', _('A Pack')))
|
||||||
return res_filter
|
return res_filter
|
||||||
|
|
||||||
|
|||||||
@@ -194,7 +194,6 @@ class StockMove(models.Model):
|
|||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_string_qty_information(self):
|
def _compute_string_qty_information(self):
|
||||||
StockConfig = self.env['stock.config.settings']
|
|
||||||
UOM = self.env['product.uom']
|
UOM = self.env['product.uom']
|
||||||
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||||
void_moves = self.filtered(lambda move: move.state in ('draft', 'done', 'cancel') or move.location_id.usage != 'internal')
|
void_moves = self.filtered(lambda move: move.state in ('draft', 'done', 'cancel') or move.location_id.usage != 'internal')
|
||||||
@@ -206,9 +205,7 @@ class StockMove(models.Model):
|
|||||||
total_available = UOM._compute_qty_obj(move.product_id.uom_id, total_available, move.product_uom, round=False)
|
total_available = UOM._compute_qty_obj(move.product_id.uom_id, total_available, move.product_uom, round=False)
|
||||||
total_available = float_round(total_available, precision_digits=precision)
|
total_available = float_round(total_available, precision_digits=precision)
|
||||||
info = str(total_available)
|
info = str(total_available)
|
||||||
# look in the settings if we need to display the UoM name or not
|
if self.user_has_groups('product.group_uom'):
|
||||||
config = StockConfig.search([], limit=1, order='id DESC')
|
|
||||||
if config and config.group_uom:
|
|
||||||
info += ' ' + move.product_uom.name
|
info += ' ' + move.product_uom.name
|
||||||
if move.reserved_availability:
|
if move.reserved_availability:
|
||||||
if move.reserved_availability != total_available:
|
if move.reserved_availability != total_available:
|
||||||
@@ -380,7 +377,7 @@ class StockMove(models.Model):
|
|||||||
# if no specialized push rule has been found yet, we try to find a general one (without route)
|
# if no specialized push rule has been found yet, we try to find a general one (without route)
|
||||||
rules = Push.search(domain + [('route_id', '=', False)], order='sequence')
|
rules = Push.search(domain + [('route_id', '=', False)], order='sequence')
|
||||||
# Make sure it is not returning the return
|
# Make sure it is not returning the return
|
||||||
if rules and (not move.origin_returned_move_id or move.origin_returned_move_id.location_id.id != rules.location_dest_id.id):
|
if rules and (not move.origin_returned_move_id or move.origin_returned_move_id.location_dest_id.id != rules.location_dest_id.id):
|
||||||
rules._apply(move)
|
rules._apply(move)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -221,6 +221,13 @@ class stock_quant(osv.osv):
|
|||||||
else:
|
else:
|
||||||
self._create_account_move_line(cr, uid, quants, move, acc_valuation, acc_dest, journal_id, context=ctx)
|
self._create_account_move_line(cr, uid, quants, move, acc_valuation, acc_dest, journal_id, context=ctx)
|
||||||
|
|
||||||
|
if move.company_id.anglo_saxon_accounting and move.location_id.usage == 'supplier' and move.location_dest_id.usage == 'customer':
|
||||||
|
# Creates an account entry from stock_input to stock_output on a dropship move. https://github.com/odoo/odoo/issues/12687
|
||||||
|
ctx = context.copy()
|
||||||
|
ctx['force_company'] = move.company_id.id
|
||||||
|
journal_id, acc_src, acc_dest, acc_valuation = self._get_accounting_data_for_valuation(cr, uid, move, context=ctx)
|
||||||
|
self._create_account_move_line(cr, uid, quants, move, acc_src, acc_dest, journal_id, context=ctx)
|
||||||
|
|
||||||
def _quant_create_from_move(self, cr, uid, qty, move, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False, force_location_from=False, force_location_to=False, context=None):
|
def _quant_create_from_move(self, cr, uid, qty, move, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False, force_location_from=False, force_location_to=False, context=None):
|
||||||
quant_obj = self.pool.get('stock.quant')
|
quant_obj = self.pool.get('stock.quant')
|
||||||
quant = super(stock_quant, self)._quant_create_from_move(cr, uid, qty, move, lot_id=lot_id, owner_id=owner_id, src_package_id=src_package_id, dest_package_id=dest_package_id, force_location_from=force_location_from, force_location_to=force_location_to, context=context)
|
quant = super(stock_quant, self)._quant_create_from_move(cr, uid, qty, move, lot_id=lot_id, owner_id=owner_id, src_package_id=src_package_id, dest_package_id=dest_package_id, force_location_from=force_location_from, force_location_to=force_location_to, context=context)
|
||||||
|
|||||||
@@ -10,8 +10,16 @@ class IrHttp(models.AbstractModel):
|
|||||||
return request.httprequest.host
|
return request.httprequest.host
|
||||||
|
|
||||||
def _dispatch(self):
|
def _dispatch(self):
|
||||||
|
tracked_fields = self.pool['utm.mixin'].tracking_fields()
|
||||||
response = super(IrHttp, self)._dispatch()
|
response = super(IrHttp, self)._dispatch()
|
||||||
for var, dummy, cook in self.pool['utm.mixin'].tracking_fields():
|
|
||||||
|
|
||||||
|
# no set_cookie on Exception
|
||||||
|
if isinstance(response, Exception):
|
||||||
|
return response
|
||||||
|
|
||||||
|
for var, dummy, cook in tracked_fields:
|
||||||
if var in request.params and request.httprequest.cookies.get(var) != request.params[var]:
|
if var in request.params and request.httprequest.cookies.get(var) != request.params[var]:
|
||||||
response.set_cookie(cook, request.params[var], domain=self.get_utm_domain_cookies())
|
response.set_cookie(cook, request.params[var], domain=self.get_utm_domain_cookies())
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -458,6 +458,9 @@ var ViewManager = Widget.extend(ControlPanelMixin, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
do_load_state: function(state, warm) {
|
do_load_state: function(state, warm) {
|
||||||
|
if (state.view_type && state.view_type !== this.active_view.type) {
|
||||||
|
this.switch_mode(state.view_type, true);
|
||||||
|
}
|
||||||
this.active_view.controller.do_load_state(state, warm);
|
this.active_view.controller.do_load_state(state, warm);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1733,7 +1733,7 @@ var Column = Class.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
var aggregation_func = (this.sum && 'sum') || (this.avg && 'avg') ||
|
var aggregation_func = (this.sum && 'sum') || (this.avg && 'avg') ||
|
||||||
(this.max && 'max') || (this.min && 'min') || this.group_operator;
|
(this.max && 'max') || (this.min && 'min');
|
||||||
|
|
||||||
if (!aggregation_func) {
|
if (!aggregation_func) {
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -112,25 +112,37 @@ return AbstractWebClient.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
on_hashchange: function(event) {
|
on_hashchange: function(event) {
|
||||||
var self = this;
|
if (this._ignore_hashchange) {
|
||||||
var stringstate = event.getState(false);
|
this._ignore_hashchange = false;
|
||||||
if (!_.isEqual(this._current_state, stringstate)) {
|
return;
|
||||||
var state = event.getState(true);
|
|
||||||
if(!state.action && state.menu_id) {
|
|
||||||
self.menu.is_bound.done(function() {
|
|
||||||
self.menu.menu_click(state.menu_id);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
state._push_me = false; // no need to push state back...
|
|
||||||
this.action_manager.do_load_state(state, !!this._current_state).then(function () {
|
|
||||||
var action = self.action_manager.get_inner_action();
|
|
||||||
if (action) {
|
|
||||||
self.menu.open_action(action.action_descr.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this._current_state = stringstate;
|
|
||||||
|
var self = this;
|
||||||
|
this.clear_uncommitted_changes().then(function () {
|
||||||
|
var stringstate = event.getState(false);
|
||||||
|
if (!_.isEqual(self._current_state, stringstate)) {
|
||||||
|
var state = event.getState(true);
|
||||||
|
if(!state.action && state.menu_id) {
|
||||||
|
self.menu.is_bound.done(function() {
|
||||||
|
self.menu.menu_click(state.menu_id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
state._push_me = false; // no need to push state back...
|
||||||
|
self.action_manager.do_load_state(state, !!self._current_state).then(function () {
|
||||||
|
var action = self.action_manager.get_inner_action();
|
||||||
|
if (action) {
|
||||||
|
self.menu.open_action(action.action_descr.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self._current_state = stringstate;
|
||||||
|
}, function () {
|
||||||
|
if (event) {
|
||||||
|
self._ignore_hashchange = true;
|
||||||
|
window.location = event.originalEvent.oldURL;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
on_menu_action: function(options) {
|
on_menu_action: function(options) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ var KanbanView = View.extend({
|
|||||||
|
|
||||||
this.qweb = new QWeb(session.debug, {_s: session.origin});
|
this.qweb = new QWeb(session.debug, {_s: session.origin});
|
||||||
|
|
||||||
this.limit = this.options.limit || 40;
|
this.limit = this.options.limit || parseInt(this.fields_view.arch.attrs.limit, 10) || 40;
|
||||||
this.fields = {};
|
this.fields = {};
|
||||||
this.fields_keys = _.keys(this.fields_view.fields);
|
this.fields_keys = _.keys(this.fields_view.fields);
|
||||||
this.grouped = undefined;
|
this.grouped = undefined;
|
||||||
|
|||||||
@@ -294,7 +294,7 @@
|
|||||||
<div class="modal-body" id="sign-dialog">
|
<div class="modal-body" id="sign-dialog">
|
||||||
<p>
|
<p>
|
||||||
<span>I agree that by signing this proposal, I
|
<span>I agree that by signing this proposal, I
|
||||||
accept it on the behalf of </span><b t-field="quotation.company_id"/><span>, for an amount of </span>
|
accept it on the behalf of </span><b t-field="quotation.partner_id.commercial_partner_id"/><span>, for an amount of </span>
|
||||||
<b data-id="total_amount" t-field="quotation.amount_total"
|
<b data-id="total_amount" t-field="quotation.amount_total"
|
||||||
t-options='{"widget": "monetary", "display_currency": quotation.pricelist_id.currency_id}'/>
|
t-options='{"widget": "monetary", "display_currency": quotation.pricelist_id.currency_id}'/>
|
||||||
<span>with payment terms: </span><b t-field="quotation.payment_term_id"/>.
|
<span>with payment terms: </span><b t-field="quotation.payment_term_id"/>.
|
||||||
@@ -321,7 +321,7 @@
|
|||||||
<div class="modal-body" id="sign-dialog">
|
<div class="modal-body" id="sign-dialog">
|
||||||
<p>
|
<p>
|
||||||
<span>I agree that by paying this proposal, I
|
<span>I agree that by paying this proposal, I
|
||||||
accept it on the behalf of </span><b t-field="quotation.company_id"/><span>, for an amount of </span>
|
accept it on the behalf of </span><b t-field="quotation.partner_id.commercial_partner_id"/><span>, for an amount of </span>
|
||||||
<b data-id="total_amount" t-field="quotation.amount_total"
|
<b data-id="total_amount" t-field="quotation.amount_total"
|
||||||
t-options='{"widget": "monetary", "display_currency": quotation.pricelist_id.currency_id}'/>
|
t-options='{"widget": "monetary", "display_currency": quotation.pricelist_id.currency_id}'/>
|
||||||
<span>with payment terms: </span><b t-field="quotation.payment_term_id"/>.
|
<span>with payment terms: </span><b t-field="quotation.payment_term_id"/>.
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ class Product(models.Model):
|
|||||||
taxes = partner.property_account_position_id.map_tax(self.taxes_id)
|
taxes = partner.property_account_position_id.map_tax(self.taxes_id)
|
||||||
return taxes.compute_all(public and self.lst_price or self.with_context(context).price, pricelist.currency_id, qty, product=self, partner=partner)[ret]
|
return taxes.compute_all(public and self.lst_price or self.with_context(context).price, pricelist.currency_id, qty, product=self, partner=partner)[ret]
|
||||||
|
|
||||||
|
|
||||||
class ProductAttribute(models.Model):
|
class ProductAttribute(models.Model):
|
||||||
_inherit = "product.attribute"
|
_inherit = "product.attribute"
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from . import test_new_fields
|
|||||||
from . import test_onchange
|
from . import test_onchange
|
||||||
from . import test_field_conversions
|
from . import test_field_conversions
|
||||||
from . import test_attributes
|
from . import test_attributes
|
||||||
|
from . import test_one2many
|
||||||
from . import test_ui
|
from . import test_ui
|
||||||
from . import test_no_infinite_recursion
|
from . import test_no_infinite_recursion
|
||||||
from . import test_domain
|
from . import test_domain
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ class TestOnChange(common.TransactionCase):
|
|||||||
self.assertEqual(values, {
|
self.assertEqual(values, {
|
||||||
'name': partner.name,
|
'name': partner.name,
|
||||||
'partner': partner.id,
|
'partner': partner.id,
|
||||||
'lines': [(5,), (4, line.id)],
|
'lines': [(6, 0, [line.id])],
|
||||||
})
|
})
|
||||||
|
|
||||||
# modify 'partner'
|
# modify 'partner'
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from openerp.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class One2manyCase(TransactionCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(One2manyCase, self).setUp()
|
||||||
|
self.Line = self.env["test_new_api.multi.line"]
|
||||||
|
self.multi = self.env["test_new_api.multi"].create({
|
||||||
|
"name": "What is up?"
|
||||||
|
})
|
||||||
|
|
||||||
|
def operations(self):
|
||||||
|
"""Run operations on o2m fields to check all works fine."""
|
||||||
|
# Check the lines first
|
||||||
|
self.assertItemsEqual(
|
||||||
|
self.multi.lines.mapped('name'),
|
||||||
|
map(str, range(10)))
|
||||||
|
# Modify the first line and drop the last one
|
||||||
|
self.multi.lines[0].name = "hello"
|
||||||
|
self.multi.lines = self.multi.lines[:-1]
|
||||||
|
self.assertEqual(len(self.multi.lines), 9)
|
||||||
|
self.assertIn("hello", self.multi.lines.mapped('name'))
|
||||||
|
# Invalidate the cache and check again; this crashes if the value
|
||||||
|
# of self.multi.lines in cache contains new records
|
||||||
|
self.multi.invalidate_cache()
|
||||||
|
self.assertEqual(len(self.multi.lines), 9)
|
||||||
|
self.assertIn("hello", self.multi.lines.mapped('name'))
|
||||||
|
|
||||||
|
def test_new_one_by_one(self):
|
||||||
|
"""Check lines created with ``new()`` and appended one by one."""
|
||||||
|
for name in range(10):
|
||||||
|
self.multi.lines |= self.Line.new({"name": str(name)})
|
||||||
|
self.operations()
|
||||||
|
|
||||||
|
def test_new_single(self):
|
||||||
|
"""Check lines created with ``new()`` and added in one step."""
|
||||||
|
self.multi.lines = self.Line.browse(
|
||||||
|
[self.Line.new({"name": str(name)}).id for name in range(10)]
|
||||||
|
)
|
||||||
|
self.operations()
|
||||||
|
|
||||||
|
def test_create_one_by_one(self):
|
||||||
|
"""Check lines created with ``create()`` and appended one by one."""
|
||||||
|
for name in range(10):
|
||||||
|
self.multi.lines |= self.Line.create({"name": str(name)})
|
||||||
|
self.operations()
|
||||||
|
|
||||||
|
def test_create_single(self):
|
||||||
|
"""Check lines created with ``create()`` and added in one step."""
|
||||||
|
self.multi.lines = self.Line.browse(
|
||||||
|
[self.Line.create({"name": str(name)}).id for name in range(10)]
|
||||||
|
)
|
||||||
|
self.operations()
|
||||||
|
|
||||||
|
def test_rpcstyle_one_by_one(self):
|
||||||
|
"""Check lines created with RPC style and appended one by one."""
|
||||||
|
for name in range(10):
|
||||||
|
self.multi.lines = [(0, 0, {"name": str(name)})]
|
||||||
|
self.operations()
|
||||||
|
|
||||||
|
def test_rpcstyle_single(self):
|
||||||
|
"""Check lines created with RPC style and added in one step"""
|
||||||
|
self.multi.lines = [(0, 0, {'name': str(name)}) for name in range(10)]
|
||||||
|
self.operations()
|
||||||
+6
-4
@@ -871,10 +871,12 @@ class Field(object):
|
|||||||
env.invalidate(spec)
|
env.invalidate(spec)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# simply write to the database, and update cache
|
# Write to database
|
||||||
write_value = self.convert_to_write(self.convert_to_record(value, record), record)
|
write_value = self.convert_to_write(self.convert_to_record(value, record), record)
|
||||||
record.write({self.name: write_value})
|
record.write({self.name: write_value})
|
||||||
record._cache[self] = value
|
# Update the cache unless value contains a new record
|
||||||
|
if not (self.relational and not all(value)):
|
||||||
|
record._cache[self] = value
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
#
|
#
|
||||||
@@ -1835,7 +1837,7 @@ class _RelationalMulti(_Relational):
|
|||||||
|
|
||||||
def convert_to_write(self, value, record):
|
def convert_to_write(self, value, record):
|
||||||
# make result with new and existing records
|
# make result with new and existing records
|
||||||
result = [(5,)]
|
result = [(6, 0, [])]
|
||||||
for record in value:
|
for record in value:
|
||||||
if not record.id:
|
if not record.id:
|
||||||
values = {name: record[name] for name in record._cache}
|
values = {name: record[name] for name in record._cache}
|
||||||
@@ -1846,7 +1848,7 @@ class _RelationalMulti(_Relational):
|
|||||||
values = record._convert_to_write(values)
|
values = record._convert_to_write(values)
|
||||||
result.append((1, record.id, values))
|
result.append((1, record.id, values))
|
||||||
else:
|
else:
|
||||||
result.append((4, record.id))
|
result[0][2].append(record.id)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def convert_to_onchange(self, value, record, fnames=()):
|
def convert_to_onchange(self, value, record, fnames=()):
|
||||||
|
|||||||
+1
-2
@@ -3890,8 +3890,7 @@ class BaseModel(object):
|
|||||||
``(6, _, ids)``
|
``(6, _, ids)``
|
||||||
replaces all existing records in the set by the ``ids`` list,
|
replaces all existing records in the set by the ``ids`` list,
|
||||||
equivalent to using the command ``5`` followed by a command
|
equivalent to using the command ``5`` followed by a command
|
||||||
``4`` for each ``id`` in ``ids``. Can not be used on
|
``4`` for each ``id`` in ``ids``.
|
||||||
:class:`~openerp.fields.One2many`.
|
|
||||||
|
|
||||||
.. note:: Values marked as ``_`` in the list above are ignored and
|
.. note:: Values marked as ``_`` in the list above are ignored and
|
||||||
can be anything, generally ``0`` or ``False``.
|
can be anything, generally ``0`` or ``False``.
|
||||||
|
|||||||
@@ -877,7 +877,11 @@ class one2many(_column):
|
|||||||
ids2 = act[2] or [0]
|
ids2 = act[2] or [0]
|
||||||
cr.execute('select id from '+_table+' where '+self._fields_id+'=%s and id <> ALL (%s)', (id,ids2))
|
cr.execute('select id from '+_table+' where '+self._fields_id+'=%s and id <> ALL (%s)', (id,ids2))
|
||||||
ids3 = map(lambda x:x[0], cr.fetchall())
|
ids3 = map(lambda x:x[0], cr.fetchall())
|
||||||
obj.write(cr, user, ids3, {self._fields_id:False}, context=context or {})
|
inverse_field = obj._fields.get(self._fields_id)
|
||||||
|
if getattr(inverse_field, "ondelete", None) == "cascade":
|
||||||
|
obj.unlink(cr, user, ids3, context=context)
|
||||||
|
else:
|
||||||
|
obj.write(cr, user, ids3, {self._fields_id: False}, context=context or {})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None):
|
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user