[MERGE] forward port branch saas-11.3 up to 27d8daf8a7

This commit is contained in:
Christophe Simonis
2018-08-14 19:43:32 +02:00
36 changed files with 118 additions and 97 deletions
+2 -6
View File
@@ -124,12 +124,8 @@ Best Regards,'''))
@api.model @api.model
def _verify_fiscalyear_last_day(self, company_id, last_day, last_month): def _verify_fiscalyear_last_day(self, company_id, last_day, last_month):
company = self.browse(company_id) # FIXME: Remove this method in master
last_day = last_day or (company and company.fiscalyear_last_day) or 31 return last_day
last_month = last_month or (company and company.fiscalyear_last_month) or 12
current_year = datetime.now().year
last_day_of_month = calendar.monthrange(current_year, last_month)[1]
return last_day > last_day_of_month and last_day_of_month or last_day
@api.multi @api.multi
def compute_fiscalyear_dates(self, current_date): def compute_fiscalyear_dates(self, current_date):
-14
View File
@@ -52,11 +52,6 @@
<!-- Is there a discount on at least one line? --> <!-- Is there a discount on at least one line? -->
<t t-set="display_discount" t-value="any([l.discount for l in o.invoice_line_ids])"/> <t t-set="display_discount" t-value="any([l.discount for l in o.invoice_line_ids])"/>
<!-- show only in sale invoice -->
<t t-set="type_is_out" t-value="o.type == 'out_invoice'"/>
<!-- if Rounding Method is computed per line -->
<t t-set="display_taxamount"
t-value="o.company_id.tax_calculation_rounding_method == 'round_per_line'"/>
<table class="table table-condensed" name="invoice_line_table"> <table class="table table-condensed" name="invoice_line_table">
<thead> <thead>
@@ -67,7 +62,6 @@
<th class="text-right">Unit Price</th> <th class="text-right">Unit Price</th>
<th t-if="display_discount" class="text-right">Disc.(%)</th> <th t-if="display_discount" class="text-right">Disc.(%)</th>
<th class="text-right">Taxes</th> <th class="text-right">Taxes</th>
<th t-if="display_taxamount and type_is_out" class="text-right">Tax Amount</th>
<th class="text-right">Amount</th> <th class="text-right">Amount</th>
</tr> </tr>
</thead> </thead>
@@ -88,13 +82,6 @@
<td class="text-right"> <td class="text-right">
<span t-esc="', '.join(map(lambda x: (x.description or x.name), l.invoice_line_tax_ids))"/> <span t-esc="', '.join(map(lambda x: (x.description or x.name), l.invoice_line_tax_ids))"/>
</td> </td>
<td t-if="display_taxamount and type_is_out" class="text-right">
<t t-set="taxes"
t-value="l.invoice_line_tax_ids.compute_all(l.price_unit, l.currency_id, l.quantity)"/>
<t t-set="tax_amount"
t-value="taxes and (taxes['total_included'] - taxes['base']) or 0.0"/>
<span t-esc="tax_amount" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
</td>
<td class="text-right" id="subtotal"> <td class="text-right" id="subtotal">
<span t-field="l.price_subtotal" <span t-field="l.price_subtotal"
t-options='{"widget": "monetary", "display_currency": o.currency_id}'/> t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
@@ -106,7 +93,6 @@
<td></td> <td></td>
<td></td> <td></td>
<td t-if="display_discount"></td> <td t-if="display_discount"></td>
<td t-if="display_taxamount and type_is_out"></td>
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
-11
View File
@@ -36,17 +36,6 @@ class FinancialYearOpeningWizard(models.TransientModel):
""" Forces fiscal year setup state to 'undone'.""" """ Forces fiscal year setup state to 'undone'."""
self.company_id.account_setup_fy_data_done = False self.company_id.account_setup_fy_data_done = False
@api.multi
def write(self, vals):
if 'fiscalyear_last_day' in vals or 'fiscalyear_last_month' in vals:
for wizard in self:
company = wizard.company_id
vals['fiscalyear_last_day'] = company._verify_fiscalyear_last_day(
company.id,
vals.get('fiscalyear_last_day'),
vals.get('fiscalyear_last_month'))
return super(FinancialYearOpeningWizard, self).write(vals)
class SetupBarBankConfigWizard(models.TransientModel): class SetupBarBankConfigWizard(models.TransientModel):
_inherits = {'res.partner.bank': 'res_partner_bank_id'} _inherits = {'res.partner.bank': 'res_partner_bank_id'}
@@ -127,6 +127,9 @@ class IrModelFieldsAnonymizeWizard(models.TransientModel):
@api.multi @api.multi
def anonymize_database(self): def anonymize_database(self):
"""Sets the 'anonymized' state to defined fields""" """Sets the 'anonymized' state to defined fields"""
# pylint: disable=W0101
raise UserError("""The Odoo Migration Platform no longer accepts anonymized databases.\n
If you wish for your data to remain private during migration, please contact us at upgrade@odoo.com""")
self.ensure_one() self.ensure_one()
# create a new history record: # create a new history record:
+2
View File
@@ -707,6 +707,8 @@ class Lead(models.Model):
@api.model @api.model
def _get_duplicated_leads_by_emails(self, partner_id, email, include_lost=False): def _get_duplicated_leads_by_emails(self, partner_id, email, include_lost=False):
""" Search for opportunities that have the same partner and that arent done or cancelled """ """ Search for opportunities that have the same partner and that arent done or cancelled """
if not email:
return []
partner_match_domain = [] partner_match_domain = []
for email in set(email_split(email) + [email]): for email in set(email_split(email) + [email]):
partner_match_domain.append(('email_from', '=ilike', email)) partner_match_domain.append(('email_from', '=ilike', email))
+3
View File
@@ -88,6 +88,9 @@ class SaleOrder(models.Model):
def _create_delivery_line(self, carrier, price_unit): def _create_delivery_line(self, carrier, price_unit):
SaleOrderLine = self.env['sale.order.line'] SaleOrderLine = self.env['sale.order.line']
if self.partner_id:
# set delivery detail in the customer language
carrier = carrier.with_context(lang=self.partner_id.lang)
# Apply fiscal position # Apply fiscal position
taxes = carrier.product_id.taxes_id.filtered(lambda t: t.company_id.id == self.company_id.id) taxes = carrier.product_id.taxes_id.filtered(lambda t: t.company_id.id == self.company_id.id)
@@ -53,6 +53,7 @@ class HrPayslip(models.Model):
@api.multi @api.multi
def action_payslip_done(self): def action_payslip_done(self):
res = super(HrPayslip, self).action_payslip_done()
precision = self.env['decimal.precision'].precision_get('Payroll') precision = self.env['decimal.precision'].precision_get('Payroll')
for slip in self: for slip in self:
@@ -138,7 +139,7 @@ class HrPayslip(models.Model):
move = self.env['account.move'].create(move_dict) move = self.env['account.move'].create(move_dict)
slip.write({'move_id': move.id, 'date': date}) slip.write({'move_id': move.id, 'date': date})
move.post() move.post()
return super(HrPayslip, self).action_payslip_done() return res
class HrSalaryRule(models.Model): class HrSalaryRule(models.Model):
+1 -1
View File
@@ -358,7 +358,7 @@ class Escpos:
else: else:
self._raw(string) self._raw(string)
raw += S_RASTER_N raw += S_RASTER_N.encode('utf-8')
buffer = "%02X%02X%02X%02X" % (int((size[0]/size[1])/8), 0, size[1], 0) buffer = "%02X%02X%02X%02X" % (int((size[0]/size[1])/8), 0, size[1], 0)
raw += codecs.decode(buffer, 'hex') raw += codecs.decode(buffer, 'hex')
buffer = "" buffer = ""
+8 -1
View File
@@ -108,7 +108,14 @@
<td></td> <td></td>
<td></td> <td></td>
<td t-if="display_discount" groups="sale.group_discount_per_so_line"></td> <td t-if="display_discount" groups="sale.group_discount_per_so_line"></td>
<td t-att-colspan="o.company_id.country_id.code == 'IN' and 5 or 1"></td> <td t-if="len(o.tax_line_ids) > 0"></td>
<td></td>
<t t-if="o.company_id.country_id.code == 'IN'">
<td t-if="is_cgst"></td>
<td t-if="is_cgst"></td>
<td t-if="is_igst"></td>
<td t-if="is_cess"></td>
</t>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -2,8 +2,8 @@
<odoo> <odoo>
<template id="gst_report_picking_inherit" inherit_id="stock.report_picking"> <template id="gst_report_picking_inherit" inherit_id="stock.report_picking">
<xpath expr="//span[@t-field='move.product_id.description_picking']" position="after"> <xpath expr="//span[@t-field='ml.product_id.description_picking']" position="after">
<t t-if="move.product_id and move.product_id.l10n_in_hsn_code and o.company_id.country_id.code == 'IN'"><h6><strong class="ml16">HSN/SAC Code:</strong> <span t-field="move.product_id.l10n_in_hsn_code"/></h6></t> <t t-if="ml.product_id and ml.product_id.l10n_in_hsn_code and o.company_id.country_id.code == 'IN'"><h6><strong class="ml16">HSN/SAC Code:</strong> <span t-field="ml.product_id.l10n_in_hsn_code"/></h6></t>
</xpath> </xpath>
</template> </template>
+14
View File
@@ -176,6 +176,20 @@ class MailController(http.Controller):
models that have an access_token may apply variations on this. models that have an access_token may apply variations on this.
""" """
# ==============================================================================================
# This block of code disappeared on saas-11.3 to be reintroduced by TBE.
# This is needed because after a migration from an older version to saas-11.3, the link
# received by mail with a message_id no longer work.
# So this block of code is needed to guarantee the backward compatibility of those links.
if kwargs.get('message_id'):
try:
message = request.env['mail.message'].sudo().browse(int(kwargs['message_id'])).exists()
except:
message = request.env['mail.message']
if message:
model, res_id = message.model, message.res_id
# ==============================================================================================
if res_id and isinstance(res_id, pycompat.string_types): if res_id and isinstance(res_id, pycompat.string_types):
res_id = int(res_id) res_id = int(res_id)
return self._redirect_to_record(model, res_id, access_token) return self._redirect_to_record(model, res_id, access_token)
+2
View File
@@ -387,6 +387,8 @@ class MailActivityMixin(models.AbstractModel):
record.activity_date_deadline = record.activity_ids[:1].date_deadline record.activity_date_deadline = record.activity_ids[:1].date_deadline
def _search_activity_date_deadline(self, operator, operand): def _search_activity_date_deadline(self, operator, operand):
if operator == '=' and not operand:
return [('activity_ids', '=', False)]
return [('activity_ids.date_deadline', operator, operand)] return [('activity_ids.date_deadline', operator, operand)]
@api.model @api.model
+1 -1
View File
@@ -35,7 +35,7 @@ class MailThread(models.AbstractModel):
""" Override to update the parent mail statistics. The parent is found """ Override to update the parent mail statistics. The parent is found
by using the References header of the incoming message and looking for by using the References header of the incoming message and looking for
matching message_id in mail.mail.statistics. """ matching message_id in mail.mail.statistics. """
if message.get('References'): if message.get('References') and routes:
message_ids = [x.strip() for x in decode_smtp_header(message['References']).split()] message_ids = [x.strip() for x in decode_smtp_header(message['References']).split()]
self.env['mail.mail.statistics'].set_opened(mail_message_ids=message_ids) self.env['mail.mail.statistics'].set_opened(mail_message_ids=message_ids)
self.env['mail.mail.statistics'].set_replied(mail_message_ids=message_ids) self.env['mail.mail.statistics'].set_replied(mail_message_ids=message_ids)
@@ -106,7 +106,7 @@ class MailMailStats(models.Model):
def set_opened(self, mail_mail_ids=None, mail_message_ids=None): def set_opened(self, mail_mail_ids=None, mail_message_ids=None):
statistics = self._get_records(mail_mail_ids, mail_message_ids, [('opened', '=', False)]) statistics = self._get_records(mail_mail_ids, mail_message_ids, [('opened', '=', False)])
statistics.write({'opened': fields.Datetime.now()}) statistics.write({'opened': fields.Datetime.now(), 'bounced': False})
return statistics return statistics
def set_clicked(self, mail_mail_ids=None, mail_message_ids=None): def set_clicked(self, mail_mail_ids=None, mail_message_ids=None):
@@ -120,6 +120,7 @@ class MailMailStats(models.Model):
return statistics return statistics
def set_bounced(self, mail_mail_ids=None, mail_message_ids=None): def set_bounced(self, mail_mail_ids=None, mail_message_ids=None):
statistics = self._get_records(mail_mail_ids, mail_message_ids, [('bounced', '=', False)]) statistics = self._get_records(
mail_mail_ids, mail_message_ids, [('bounced', '=', False), ('opened', '=', False)])
statistics.write({'bounced': fields.Datetime.now()}) statistics.write({'bounced': fields.Datetime.now()})
return statistics return statistics
+1 -1
View File
@@ -25,7 +25,7 @@
</option> </option>
</select> </select>
</div> </div>
<div class="form-group col-md-4"> <div t-attf-class="form-group #{is_variant_applied ? 'col-md-4' : 'col-md-8'}">
<label>Report:</label> <label>Report:</label>
<select class="o_input o_mrp_bom_report_type"> <select class="o_input o_mrp_bom_report_type">
<option t-att-data-type="'all'">BoM Structure &amp; Cost</option> <option t-att-data-type="'all'">BoM Structure &amp; Cost</option>
+2 -2
View File
@@ -134,7 +134,7 @@ odoo.define('payment.payment_form', function (require) {
self.displayError( self.displayError(
_t('Server Error'), _t('Server Error'),
_t("We are not able to add your payment method at the moment.") + _t("We are not able to add your payment method at the moment.") +
data.data.message message.data.message
); );
}); });
} }
@@ -180,7 +180,7 @@ odoo.define('payment.payment_form', function (require) {
self.displayError( self.displayError(
_t('Server Error'), _t('Server Error'),
_t("We are not able to redirect you to the payment form. ") + _t("We are not able to redirect you to the payment form. ") +
data.data.message message.data.message
); );
}); });
} }
+6 -5
View File
@@ -40,11 +40,12 @@ class AccountInvoice(models.Model):
purchase_line_ids = self.invoice_line_ids.mapped('purchase_line_id') purchase_line_ids = self.invoice_line_ids.mapped('purchase_line_id')
purchase_ids = self.invoice_line_ids.mapped('purchase_id').filtered(lambda r: r.order_line <= purchase_line_ids) purchase_ids = self.invoice_line_ids.mapped('purchase_id').filtered(lambda r: r.order_line <= purchase_line_ids)
result['domain'] = {'purchase_id': [ domain = [('invoice_status', 'in', ['to invoice', 'no'])]
('invoice_status', 'in', ['to invoice', 'no']), if self.partner_id:
('partner_id', 'child_of', self.partner_id.id), domain += [('partner_id', 'child_of', self.partner_id.id)]
('id', 'not in', purchase_ids.ids), if purchase_ids:
]} domain += [('id', 'not in', purchase_ids.ids)]
result['domain'] = {'purchase_id': domain}
return result return result
def _prepare_invoice_line_from_po_line(self, line): def _prepare_invoice_line_from_po_line(self, line):
+4 -3
View File
@@ -98,10 +98,11 @@ class PurchaseOrder(models.Model):
if order.state in ('draft', 'sent', 'to approve'): if order.state in ('draft', 'sent', 'to approve'):
for order_line in order.order_line: for order_line in order.order_line:
if order_line.move_dest_ids: if order_line.move_dest_ids:
siblings_states = (order_line.move_dest_ids.mapped('move_orig_ids')).mapped('state') move_dest_ids = order_line.move_dest_ids.filtered(lambda m: m.state not in ('done', 'cancel'))
siblings_states = (move_dest_ids.mapped('move_orig_ids')).mapped('state')
if all(state in ('done', 'cancel') for state in siblings_states): if all(state in ('done', 'cancel') for state in siblings_states):
order_line.move_dest_ids.write({'procure_method': 'make_to_stock'}) move_dest_ids.write({'procure_method': 'make_to_stock'})
order_line.move_dest_ids._recompute_state() move_dest_ids._recompute_state()
for pick in order.picking_ids.filtered(lambda r: r.state != 'cancel'): for pick in order.picking_ids.filtered(lambda r: r.state != 'cancel'):
pick.action_cancel() pick.action_cancel()
@@ -39,18 +39,12 @@
<!-- Is there a discount on at least one line? --> <!-- Is there a discount on at least one line? -->
<t t-set="display_discount" t-value="any([l.discount for l in o.invoice_line_ids])"/> <t t-set="display_discount" t-value="any([l.discount for l in o.invoice_line_ids])"/>
<!-- show only in sale invoice -->
<t t-set="type_is_out" t-value="o.type == 'out_invoice'"/>
<!-- if Rounding Method is computed per line -->
<t t-set="display_taxamount"
t-value="o.company_id.tax_calculation_rounding_method == 'round_per_line'"/>
<table class="table table-condensed"> <table class="table table-condensed">
<thead> <thead>
<tr> <tr>
<th>Description</th> <th>Description</th>
<th class="text-right">Taxes</th> <th class="text-right">Taxes</th>
<th t-if="display_taxamount and type_is_out" class="text-right">Tax Amount</th>
<th class="text-right">Intrastat</th> <th class="text-right">Intrastat</th>
<th class="text-right">Weight</th> <th class="text-right">Weight</th>
<th class="text-right">Quantity</th> <th class="text-right">Quantity</th>
@@ -64,13 +58,6 @@
<tr t-foreach="o.invoice_line_ids" t-as="l"> <tr t-foreach="o.invoice_line_ids" t-as="l">
<td><span t-field="l.name"/></td> <td><span t-field="l.name"/></td>
<td class="text-right"><span t-esc="', '.join(map(lambda x: x.name, l.invoice_line_tax_ids))"/></td> <td class="text-right"><span t-esc="', '.join(map(lambda x: x.name, l.invoice_line_tax_ids))"/></td>
<td t-if="display_taxamount and type_is_out" class="text-right">
<t t-set="taxes"
t-value="l.invoice_line_tax_ids.compute_all(l.price_unit, l.currency_id, l.quantity)"/>
<t t-set="tax_amount"
t-value="taxes and (taxes['total_included'] - taxes['base']) or 0.0"/>
<span t-esc="tax_amount" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
</td>
<td class="text-right"><span t-esc="l.product_id.intrastat_id.name"/></td> <td class="text-right"><span t-esc="l.product_id.intrastat_id.name"/></td>
<td class="text-right"><span t-esc="l.product_id.weight"/></td> <td class="text-right"><span t-esc="l.product_id.weight"/></td>
<td class="text-right"><span t-field="l.quantity"/></td> <td class="text-right"><span t-field="l.quantity"/></td>
@@ -99,7 +86,7 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td>Taxes Amount</td> <td>Taxes</td>
<td class="text-right"> <td class="text-right">
<span t-field="o.amount_tax" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/> <span t-field="o.amount_tax" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
</td> </td>
+6
View File
@@ -667,6 +667,12 @@ class SaleOrder(models.Model):
'target': 'self', 'target': 'self',
'res_id': self.id, 'res_id': self.id,
} }
else:
action = self.env.ref('sale.action_quotations', False)
if action:
result = action.read()[0]
result['res_id'] = self.id
return result
return super(SaleOrder, self).get_access_action(access_uid) return super(SaleOrder, self).get_access_action(access_uid)
def get_mail_url(self): def get_mail_url(self):
@@ -68,9 +68,6 @@
<!-- Is there a discount on at least one line? --> <!-- Is there a discount on at least one line? -->
<t t-set="display_discount" t-value="any([l.discount for l in doc.order_line])"/> <t t-set="display_discount" t-value="any([l.discount for l in doc.order_line])"/>
<!-- if Rounding Method is computed per line -->
<t t-set="display_taxamount"
t-value="doc.company_id.tax_calculation_rounding_method == 'round_per_line'"/>
<t t-foreach="doc.order_lines_layouted()" t-as="page"> <t t-foreach="doc.order_lines_layouted()" t-as="page">
<table class="table table-condensed"> <table class="table table-condensed">
@@ -81,7 +78,6 @@
<th class="text-right">Unit Price</th> <th class="text-right">Unit Price</th>
<th t-if="display_discount" class="text-right" groups="sale.group_discount_per_so_line">Disc.(%)</th> <th t-if="display_discount" class="text-right" groups="sale.group_discount_per_so_line">Disc.(%)</th>
<th class="text-right">Taxes</th> <th class="text-right">Taxes</th>
<th t-if="display_taxamount" class="text-right">Tax Amount</th>
<th class="text-right" groups="sale.group_show_price_subtotal">Amount</th> <th class="text-right" groups="sale.group_show_price_subtotal">Amount</th>
<th class="text-right price_tax_included" groups="sale.group_show_price_total">Total Price</th> <th class="text-right price_tax_included" groups="sale.group_show_price_total">Total Price</th>
</tr> </tr>
@@ -114,10 +110,6 @@
<td class="text-right"> <td class="text-right">
<span t-esc="', '.join(map(lambda x: (x.description or x.name), l.tax_id))"/> <span t-esc="', '.join(map(lambda x: (x.description or x.name), l.tax_id))"/>
</td> </td>
<td t-if="display_taxamount" class="text-right">
<span t-field="l.price_tax"
t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/>
</td>
<td class="text-right" groups="sale.group_show_price_subtotal"> <td class="text-right" groups="sale.group_show_price_subtotal">
<span t-field="l.price_subtotal" <span t-field="l.price_subtotal"
t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/> t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/>
@@ -15,12 +15,10 @@
<field name="model">account.invoice</field> <field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/> <field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//label" position="before"> <xpath expr="//div[@name='button_box']" position="inside">
<div class="oe_button_box" name="button_box" groups="base.group_user"> <button name="%(sale_timesheet.action_timesheet_from_invoice)d" type="action" class="oe_stat_button" icon="fa-calendar" attrs="{'invisible':[('timesheet_count','=', 0)]}">
<button name="%(sale_timesheet.action_timesheet_from_invoice)d" type="action" class="oe_stat_button" icon="fa-calendar" attrs="{'invisible':[('timesheet_count','=', 0)]}"> <field name="timesheet_count" widget="statinfo" string="Timesheets"/>
<field name="timesheet_count" widget="statinfo" string="Timesheets"/> </button>
</button>
</div>
</xpath> </xpath>
</field> </field>
</record> </record>
-2
View File
@@ -711,8 +711,6 @@ class Picking(models.Model):
if product and product.tracking != 'none': if product and product.tracking != 'none':
if not line.lot_name and not line.lot_id: if not line.lot_name and not line.lot_id:
raise UserError(_('You need to supply a Lot/Serial number for product %s.') % product.display_name) raise UserError(_('You need to supply a Lot/Serial number for product %s.') % product.display_name)
elif line.qty_done == 0:
raise UserError(_('You cannot validate a transfer if you have not processed any quantity for %s.') % product.display_name)
if no_quantities_done: if no_quantities_done:
view = self.env.ref('stock.view_immediate_transfer') view = self.env.ref('stock.view_immediate_transfer')
+6 -7
View File
@@ -3150,7 +3150,7 @@ class StockMove(TransactionCase):
def test_immediate_validate_4(self): def test_immediate_validate_4(self):
""" In a picking with a single available tracked by lot move, clicking on validate without """ In a picking with a single available tracked by lot move, clicking on validate without
filling any quantities should open an UserError. filling any quantities should pop up the immediate transfer wizard.
""" """
partner = self.env['res.partner'].create({'name': 'Jean'}) partner = self.env['res.partner'].create({'name': 'Jean'})
lot1 = self.env['stock.production.lot'].create({ lot1 = self.env['stock.production.lot'].create({
@@ -3176,12 +3176,11 @@ class StockMove(TransactionCase):
}) })
picking.action_confirm() picking.action_confirm()
picking.action_assign() picking.action_assign()
# No quantites/lot filled, it should raise. # No quantites filled, immediate transfer wizard should pop up.
with self.assertRaises(UserError): immediate_trans_wiz_dict = picking.button_validate()
picking.button_validate() self.assertEqual(immediate_trans_wiz_dict.get('res_model'), 'stock.immediate.transfer')
picking.move_lines.move_line_ids[0].qty_done = 5.0 immediate_trans_wiz = self.env[immediate_trans_wiz_dict['res_model']].browse(immediate_trans_wiz_dict['res_id'])
# All the information are present (lots and quantities), the wizard won't be opened. immediate_trans_wiz.process()
picking.button_validate()
self.assertEqual(picking.move_lines.quantity_done, 5.0) self.assertEqual(picking.move_lines.quantity_done, 5.0)
# Check move_lines data # Check move_lines data
@@ -18,6 +18,7 @@ This module allows you to easily add extra costs on pickings and decide the spli
], ],
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'security/stock_landed_cost_security.xml',
'data/stock_landed_cost_data.xml', 'data/stock_landed_cost_data.xml',
'views/product_views.xml', 'views/product_views.xml',
'views/stock_landed_cost_views.xml', 'views/stock_landed_cost_views.xml',
@@ -51,6 +51,8 @@ class LandedCost(models.Model):
account_journal_id = fields.Many2one( account_journal_id = fields.Many2one(
'account.journal', 'Account Journal', 'account.journal', 'Account Journal',
required=True, states={'done': [('readonly', True)]}) required=True, states={'done': [('readonly', True)]})
company_id = fields.Many2one('res.company', string="Company",
related='account_journal_id.company_id')
@api.one @api.one
@api.depends('cost_lines.price_unit') @api.depends('cost_lines.price_unit')
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="0">
<record model="ir.rule" id="stock_landed_cost_rule">
<field name="name">stock_landed_cost multi-company</field>
<field name="model_id" search="[('model','=','stock.landed.cost')]" model="ir.model"/>
<field name="global" eval="True"/>
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record>
</data>
</odoo>
@@ -612,12 +612,12 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
}).then(function (result) { }).then(function (result) {
self.do_action(result, { self.do_action(result, {
on_reverse_breadcrumb: function () { on_reverse_breadcrumb: function () {
if (self.renderer.alertFields.length) { if (!_.isEmpty(self.renderer.alertFields)) {
self.renderer.displayTranslationAlert(); self.renderer.displayTranslationAlert();
} }
return false return false;
}, },
}) });
}); });
}, },
}); });
@@ -958,6 +958,9 @@ var VideoWidget = MediaWidget.extend({
return {errorCode: 1}; return {errorCode: 1};
} }
if (ytMatch) {
$video.attr('src', $video.attr('src') + '&rel=0');
}
if (options.loop && (ytMatch || vimMatch)) { if (options.loop && (ytMatch || vimMatch)) {
$video.attr('src', $video.attr('src') + '&loop=1'); $video.attr('src', $video.attr('src') + '&loop=1');
} }
+1
View File
@@ -38,3 +38,4 @@ Raúl Martín raul.martin@braintec-group.com https://github.com/BT-rmartin
Silvan Wyden silvan.wyden@braintec-group.com https://github.com/BT-swyden Silvan Wyden silvan.wyden@braintec-group.com https://github.com/BT-swyden
Timka Piric Muratovic timka.piric@braintec-group.com https://github.com/BT-tpiric Timka Piric Muratovic timka.piric@braintec-group.com https://github.com/BT-tpiric
Pascal Zenklusen pascal.zenklusen@braintec-group.com https://github.com/BT-pzenklusen Pascal Zenklusen pascal.zenklusen@braintec-group.com https://github.com/BT-pzenklusen
Nadal Francisco Garcia nadal.francisco@braintec-group.com https://github.com/BT-nfrancisco
+11
View File
@@ -0,0 +1,11 @@
Italy, 2018-08-08
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Marco Calcagni mcalcagni@dinamicheaziendali.it https://github.com/As400it
+2 -2
View File
@@ -6,9 +6,9 @@
"base.lang_bs_BA","Bosnian / bosanski jezik","bs_BA","bs","Left-to-Right","[]",",",,"%d.%m.%Y","%H:%M:%S","True","7" "base.lang_bs_BA","Bosnian / bosanski jezik","bs_BA","bs","Left-to-Right","[]",",",,"%d.%m.%Y","%H:%M:%S","True","7"
"base.lang_bg","Bulgarian / български език","bg_BG","bg","Left-to-Right","[3,0]",",",,"%d.%m.%Y","%H,%M,%S","True","1" "base.lang_bg","Bulgarian / български език","bg_BG","bg","Left-to-Right","[3,0]",",",,"%d.%m.%Y","%H,%M,%S","True","1"
"base.lang_ca_ES","Catalan / Català","ca_ES","ca_ES","Left-to-Right","[3,0]",",",".","%d/%m/%Y","%H:%M:%S","True","1" "base.lang_ca_ES","Catalan / Català","ca_ES","ca_ES","Left-to-Right","[3,0]",",",".","%d/%m/%Y","%H:%M:%S","True","1"
"base.lang_zh_CN","Chinese (CN) / 简体中文","zh_CN","zh_CN","Left-to-Right","[3,0]",".",",","%Y年%m月%d日","%H时%M分%S秒","True","7" "base.lang_zh_CN","Chinese (Simplified) / 简体中文","zh_CN","zh_CN","Left-to-Right","[3,0]",".",",","%Y年%m月%d日","%H时%M分%S秒","True","7"
"base.lang_zh_HK","Chinese (HK)","zh_HK","zh_HK","Left-to-Right","[3,0]",".",",","%Y年%m月%d日 %A","%I時%M分%S秒","True","7" "base.lang_zh_HK","Chinese (HK)","zh_HK","zh_HK","Left-to-Right","[3,0]",".",",","%Y年%m月%d日 %A","%I時%M分%S秒","True","7"
"base.lang_zh_TW","Chinese (TW) / 正體字","zh_TW","zh_TW","Left-to-Right","[3,0]",".",",","%Y年%m月%d日","%H時%M分%S秒","True","7" "base.lang_zh_TW","Chinese (Traditional) / 正體字","zh_TW","zh_TW","Left-to-Right","[3,0]",".",",","%Y年%m月%d日","%H時%M分%S秒","True","7"
"base.lang_hr","Croatian / hrvatski jezik","hr_HR","hr","Left-to-Right","[]",",",,"%d.%m.%Y","%H:%M:%S","True","1" "base.lang_hr","Croatian / hrvatski jezik","hr_HR","hr","Left-to-Right","[]",",",,"%d.%m.%Y","%H:%M:%S","True","1"
"base.lang_cs_CZ","Czech / Čeština","cs_CZ","cs_CZ","Left-to-Right","[3,0]",","," ","%d.%m.%Y","%H:%M:%S","True","1" "base.lang_cs_CZ","Czech / Čeština","cs_CZ","cs_CZ","Left-to-Right","[3,0]",","," ","%d.%m.%Y","%H:%M:%S","True","1"
"base.lang_da_DK","Danish / Dansk","da_DK","da_DK","Left-to-Right","[3,0]",",",".","%d-%m-%Y","%H:%M:%S","True","1" "base.lang_da_DK","Danish / Dansk","da_DK","da_DK","Left-to-Right","[3,0]",",",".","%d-%m-%Y","%H:%M:%S","True","1"
1 id name code iso_code direction grouping decimal_point thousands_sep date_format time_format translatable week_start
6 base.lang_bs_BA Bosnian / bosanski jezik bs_BA bs Left-to-Right [] , %d.%m.%Y %H:%M:%S True 7
7 base.lang_bg Bulgarian / български език bg_BG bg Left-to-Right [3,0] , %d.%m.%Y %H,%M,%S True 1
8 base.lang_ca_ES Catalan / Català ca_ES ca_ES Left-to-Right [3,0] , . %d/%m/%Y %H:%M:%S True 1
9 base.lang_zh_CN Chinese (CN) / 简体中文 Chinese (Simplified) / 简体中文 zh_CN zh_CN Left-to-Right [3,0] . , %Y年%m月%d日 %H时%M分%S秒 True 7
10 base.lang_zh_HK Chinese (HK) zh_HK zh_HK Left-to-Right [3,0] . , %Y年%m月%d日 %A %I時%M分%S秒 True 7
11 base.lang_zh_TW Chinese (TW) / 正體字 Chinese (Traditional) / 正體字 zh_TW zh_TW Left-to-Right [3,0] . , %Y年%m月%d日 %H時%M分%S秒 True 7
12 base.lang_hr Croatian / hrvatski jezik hr_HR hr Left-to-Right [] , %d.%m.%Y %H:%M:%S True 1
13 base.lang_cs_CZ Czech / Čeština cs_CZ cs_CZ Left-to-Right [3,0] ,   %d.%m.%Y %H:%M:%S True 1
14 base.lang_da_DK Danish / Dansk da_DK da_DK Left-to-Right [3,0] , . %d-%m-%Y %H:%M:%S True 1
+3
View File
@@ -575,8 +575,11 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
IrDefault.set(model, field, value) IrDefault.set(model, field, value)
# group fields: modify group / implied groups # group fields: modify group / implied groups
current_settings = self.new(self.default_get(list(self.fields_get())))
with self.env.norecompute(): with self.env.norecompute():
for name, groups, implied_group in classified['group']: for name, groups, implied_group in classified['group']:
if self[name] == current_settings[name]:
continue
if self[name]: if self[name]:
groups.write({'implied_ids': [(4, implied_group.id)]}) groups.write({'implied_ids': [(4, implied_group.id)]})
else: else:
+4
View File
@@ -46,6 +46,10 @@ class RedirectWarning(Exception):
:param string button_text: text to put on the button that will trigger :param string button_text: text to put on the button that will trigger
the redirection. the redirection.
""" """
# using this RedirectWarning won't crash if used as an except_orm
@property
def name(self):
return self.args[0]
class AccessDenied(Exception): class AccessDenied(Exception):
+1 -4
View File
@@ -1148,10 +1148,7 @@ def formatLang(env, value, digits=None, grouping=True, monetary=False, dp=False,
return '' return ''
lang = env.context.get('lang') or env.user.company_id.partner_id.lang or 'en_US' lang = env.context.get('lang') or env.user.company_id.partner_id.lang or 'en_US'
lang_objs = env['res.lang'].search([('code', '=', lang)]) lang_obj = env['res.lang']._lang_get(lang)
if not lang_objs:
lang_objs = env['res.lang'].search([], limit=1)
lang_obj = lang_objs[0]
res = lang_obj.format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary) res = lang_obj.format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
+1 -1
View File
@@ -8,7 +8,7 @@ gevent==1.3.4 ; sys_platform != 'win32' and python_version >= '3.7'
greenlet==0.4.10 ; python_version < '3.7' greenlet==0.4.10 ; python_version < '3.7'
greenlet==0.4.13 ; python_version >= '3.7' greenlet==0.4.13 ; python_version >= '3.7'
html2text==2016.9.19 html2text==2016.9.19
Jinja2==2.8 Jinja2==2.8.1
libsass==0.12.3 libsass==0.12.3
lxml==3.7.1 ; sys_platform != 'win32' and python_version < '3.7' lxml==3.7.1 ; sys_platform != 'win32' and python_version < '3.7'
lxml==4.2.3 ; sys_platform != 'win32' and python_version >= '3.7' lxml==4.2.3 ; sys_platform != 'win32' and python_version >= '3.7'