[MERGE] forward port branch 11.0 up to fd122aec52
This commit is contained in:
@@ -24,7 +24,7 @@ class MailController(MailController):
|
||||
except AccessError:
|
||||
if record_sudo.access_token and consteq(record_sudo.access_token, access_token):
|
||||
record_action = record_sudo.with_context(
|
||||
force_website=True).get_access_action(uid)
|
||||
force_website=True).get_access_action()
|
||||
if record_action['type'] == 'ir.actions.act_url':
|
||||
return werkzeug.utils.redirect(record_action['url'])
|
||||
return super(MailController, cls)._redirect_to_record(model, res_id, access_token=access_token)
|
||||
|
||||
@@ -177,6 +177,8 @@ class AccountAccount(models.Model):
|
||||
@api.onchange('internal_type')
|
||||
def onchange_internal_type(self):
|
||||
self.reconcile = self.internal_type in ('receivable', 'payable')
|
||||
if self.internal_type == 'liquidity':
|
||||
self.reconcile = False
|
||||
|
||||
@api.onchange('code')
|
||||
def onchange_code(self):
|
||||
|
||||
@@ -1475,7 +1475,7 @@ class AccountInvoiceLine(models.Model):
|
||||
ondelete='set null', index=True, oldname='uos_id')
|
||||
product_id = fields.Many2one('product.product', string='Product',
|
||||
ondelete='restrict', index=True)
|
||||
product_image = fields.Binary('Product Image', related="product_id.image", store=False)
|
||||
product_image = fields.Binary('Product Image', related="product_id.image", store=False, readonly=True)
|
||||
account_id = fields.Many2one('account.account', string='Account',
|
||||
required=True, domain=[('deprecated', '=', False)],
|
||||
default=_default_account,
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
|
||||
<field name="currency_id" options="{'no_create': True}" groups="base.group_multi_currency"/>
|
||||
<field name="internal_type" invisible="1" readonly="1"/>
|
||||
<label for="reconcile"/>
|
||||
<div>
|
||||
<label for="reconcile" attrs="{'invisible': [('internal_type','=','liquidity')]}"/>
|
||||
<div attrs="{'invisible': [('internal_type','=','liquidity')]}">
|
||||
<field name="reconcile"/>
|
||||
<button name="action_open_reconcile" class="oe_link" type="object" string=" -> Reconcile" attrs="{'invisible': [('reconcile', '=', False)]}"/>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,7 @@ class PaymentPortal(http.Controller):
|
||||
except:
|
||||
return False
|
||||
|
||||
if request.env.user == request.env.ref('base.public_user'):
|
||||
if request.env.user._is_public():
|
||||
save_token = False # we avoid to create a token for the public user
|
||||
|
||||
token = request.env['payment.token'].sudo() # currently no support of payment tokens
|
||||
|
||||
@@ -11,7 +11,7 @@ class PortalAccount(PortalAccount):
|
||||
values = super(PortalAccount, self)._invoice_get_page_view_values(invoice, access_token, **kwargs)
|
||||
payment_inputs = request.env['payment.acquirer']._get_available_payment_input(company=invoice.company_id)
|
||||
# if not connected (using public user), the method _get_available_payment_input will return public user tokens
|
||||
is_public_user = request.env.ref('base.public_user') == request.env.user
|
||||
is_public_user = request.env.user._is_public()
|
||||
if is_public_user:
|
||||
# we should not display payment tokens owned by the public user
|
||||
payment_inputs.pop('pms', None)
|
||||
|
||||
@@ -1082,9 +1082,8 @@ class Meeting(models.Model):
|
||||
else:
|
||||
sort_fields[field] = self[field]
|
||||
if isinstance(self[field], models.BaseModel):
|
||||
name_get = self[field].name_get()
|
||||
if len(name_get) and len(name_get[0]) >= 2:
|
||||
sort_fields[field] = name_get[0][1]
|
||||
name_get = self[field].mapped('display_name')
|
||||
sort_fields[field] = name_get and name_get[0] or ''
|
||||
if r_date:
|
||||
sort_fields['sort_start'] = r_date.strftime(VIRTUALID_DATETIME_FORMAT)
|
||||
else:
|
||||
|
||||
@@ -50,10 +50,9 @@ Sidebar.include({
|
||||
* @override
|
||||
*/
|
||||
updateEnv: function (env) {
|
||||
if (this.hasAttachments) {
|
||||
this.env = env;
|
||||
this._updateAttachments().then(this._redraw.bind(this));
|
||||
}
|
||||
var _super = _.bind(this._super, this, env);
|
||||
var def = this.hasAttachments ? this._updateAttachments() : $.when();
|
||||
def.then(_super);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -146,7 +146,8 @@ class IapAccount(models.Model):
|
||||
def get(self, service_name):
|
||||
account = self.search([('service_name', '=', service_name), ('company_id', 'in', [self.env.user.company_id.id, False])])
|
||||
if not account:
|
||||
account = self.create({'service_name': service_name})
|
||||
# TODO: remove this sudo in v12 as we change the user rights.
|
||||
account = self.sudo().create({'service_name': service_name}).with_env(self.env)
|
||||
# Since the account did not exist yet, we will encounter a NoCreditError,
|
||||
# which is going to rollback the database and undo the account creation,
|
||||
# preventing the process to continue any further.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
id,code,name,reconcile,user_type_id:id,chart_template_id:id
|
||||
co_puc_110505,110505,Caja General,TRUE,account.data_account_type_liquidity,l10n_co_chart_template_generic
|
||||
co_puc_110505,110505,Caja General,FALSE,account.data_account_type_liquidity,l10n_co_chart_template_generic
|
||||
co_puc_120535,120535,Comercio al Por Mayor y al Por Menor,FALSE,account.data_account_type_current_assets,l10n_co_chart_template_generic
|
||||
co_puc_129595,129595,Diversas,FALSE,account.data_account_type_current_assets,l10n_co_chart_template_generic
|
||||
co_puc_130505,130505,Nacionales,TRUE,account.data_account_type_receivable,l10n_co_chart_template_generic
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<field name="code">0-111301</field>
|
||||
<field name="name">0-Cuenta PayPal 1</field>
|
||||
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
||||
<field name="reconcile" eval="True"/>
|
||||
<field name="reconcile" eval="False"/>
|
||||
<field name="chart_template_id" ref="account_chart_template_0"/>
|
||||
</record>
|
||||
<record id="account_account_template_0_111401" model="account.account.template">
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</t>
|
||||
</xpath>
|
||||
<xpath expr="//table[@name='invoice_line_table']" position="replace">
|
||||
<table class="table table-condensed" name="invoice_line_table">
|
||||
<table class="table table-condensed" name="invoice_line_table" groups="!sale.group_sale_layout">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
|
||||
@@ -1193,6 +1193,7 @@ class MailThread(models.AbstractModel):
|
||||
# if a new thread is created, parent is irrelevant
|
||||
message_dict.pop('parent_id', None)
|
||||
thread = MessageModel.message_new(message_dict, custom_values)
|
||||
thread_id = thread.id
|
||||
else:
|
||||
if thread_id:
|
||||
raise ValueError("Posting a message without model should be with a null res_id, to create a private message.")
|
||||
|
||||
@@ -235,7 +235,7 @@ class MassMailingCampaign(models.Model):
|
||||
mass_mailing_ids = fields.One2many(
|
||||
'mail.mass_mailing', 'mass_mailing_campaign_id',
|
||||
string='Mass Mailings')
|
||||
unique_ab_testing = fields.Boolean(string='Allow A/B Testing', default=True,
|
||||
unique_ab_testing = fields.Boolean(string='Allow A/B Testing', default=False,
|
||||
help='If checked, recipients will be mailed only once for the whole campaign. '
|
||||
'This lets you send different mailings to randomly selected recipients and test '
|
||||
'the effectiveness of the mailings, without causing duplicate messages.')
|
||||
|
||||
@@ -465,7 +465,7 @@ class PosOrder(models.Model):
|
||||
|
||||
def _filtered_for_reconciliation(self):
|
||||
filter_states = ['invoiced', 'done']
|
||||
if self.env['ir.config_parameter'].get_param('point_of_sale.order_reconcile_mode', 'all') == 'partner_only':
|
||||
if self.env['ir.config_parameter'].sudo().get_param('point_of_sale.order_reconcile_mode', 'all') == 'partner_only':
|
||||
return self.filtered(lambda order: order.state in filter_states and order.partner_id)
|
||||
return self.filtered(lambda order: order.state in filter_states)
|
||||
|
||||
|
||||
@@ -36,9 +36,13 @@ class TestAngloSaxonCommon(common.TransactionCase):
|
||||
self.product = self.product.copy({'name': 'New product','standard_price': 100})
|
||||
self.company.anglo_saxon_accounting = True
|
||||
self.product.categ_id = self.category
|
||||
self.product.property_account_expense_id = account_expense
|
||||
self.product.property_account_income_id = self.account
|
||||
sale_journal = self.env['account.journal'].create({'name': 'POS journal', 'type': 'sale', 'code': 'POS00'})
|
||||
self.pos_config.journal_id = sale_journal
|
||||
self.cash_journal = self.env['account.journal'].create({'name': 'CASH journal', 'type': 'cash', 'code': 'CSH00'})
|
||||
self.pos_config.invoice_journal_id = False
|
||||
self.pos_config.journal_ids = [self.cash_journal.id]
|
||||
|
||||
|
||||
class TestAngloSaxonFlow(TestAngloSaxonCommon):
|
||||
|
||||
@@ -37,7 +37,7 @@ def _message_post_helper(res_model='', res_id=None, message='', token='', nosubs
|
||||
access_as_sudo = _has_token_access(res_model, res_id, token=token)
|
||||
if access_as_sudo:
|
||||
record = record.sudo()
|
||||
if request.env.user == request.env.ref('base.public_user'):
|
||||
if request.env.user._is_public():
|
||||
author_id = record.partner_id.id if hasattr(record, 'partner_id') else author_id
|
||||
else:
|
||||
if not author_id:
|
||||
|
||||
@@ -123,6 +123,7 @@ class ProductProduct(models.Model):
|
||||
image_medium = fields.Binary(
|
||||
"Medium-sized image", compute='_compute_images', inverse='_set_image_medium',
|
||||
help="Image of the product variant (Medium-sized image of product template if false).")
|
||||
is_product_variant = fields.Boolean(compute='_compute_is_product_variant')
|
||||
|
||||
standard_price = fields.Float(
|
||||
'Cost', company_dependent=True,
|
||||
@@ -150,6 +151,10 @@ class ProductProduct(models.Model):
|
||||
def _get_invoice_policy(self):
|
||||
return False
|
||||
|
||||
def _compute_is_product_variant(self):
|
||||
for product in self:
|
||||
product.is_product_variant = True
|
||||
|
||||
def _compute_product_price(self):
|
||||
prices = {}
|
||||
pricelist_id_or_name = self._context.get('pricelist')
|
||||
|
||||
@@ -239,10 +239,7 @@ class ProductTemplate(models.Model):
|
||||
|
||||
def _compute_is_product_variant(self):
|
||||
for template in self:
|
||||
if template._name == 'product.template':
|
||||
template.is_product_variant = False
|
||||
else:
|
||||
template.is_product_variant = True
|
||||
template.is_product_variant = False
|
||||
|
||||
@api.model
|
||||
def _get_weight_uom_id_from_ir_config_parameter(self):
|
||||
|
||||
@@ -36,6 +36,7 @@ class TestProductCommon(common.SavepointCase):
|
||||
cls.product_1 = Product.create({
|
||||
'name': 'Courage',
|
||||
'type': 'consu',
|
||||
'default_code': 'PROD-1',
|
||||
'uom_id': cls.uom_dunit.id,
|
||||
'uom_po_id': cls.uom_dunit.id})
|
||||
|
||||
|
||||
@@ -60,6 +60,14 @@ class TestVariants(common.TestProductCommon):
|
||||
self.size_attr_value_l = self.env['product.attribute.value'].create({'name': 'L', 'attribute_id': self.size_attr.id})
|
||||
return res
|
||||
|
||||
def test_variants_is_product_variant(self):
|
||||
template = self.product_7_template
|
||||
variants = template.product_variant_ids
|
||||
self.assertFalse(template.is_product_variant,
|
||||
'Product template is not a variant')
|
||||
self.assertEqual({True}, set(v.is_product_variant for v in variants),
|
||||
'Product variants are variants')
|
||||
|
||||
def test_variants_creation_mono(self):
|
||||
test_template = self.env['product.template'].create({
|
||||
'name': 'Sofa',
|
||||
|
||||
@@ -271,7 +271,9 @@ class Project(models.Model):
|
||||
def map_tasks(self, new_project_id):
|
||||
""" copy and map tasks from old to new project """
|
||||
tasks = self.env['project.task']
|
||||
for task in self.tasks:
|
||||
# We want to copy archived task, but do not propagate an active_test context key
|
||||
task_ids = self.env['project.task'].with_context(active_test=False).search([('project_id', '=', self.id)]).ids
|
||||
for task in self.env['project.task'].browse(task_ids):
|
||||
# preserve task name and stage, normally altered during copy
|
||||
defaults = {'stage_id': task.stage_id.id,
|
||||
'name': task.name}
|
||||
@@ -283,7 +285,6 @@ class Project(models.Model):
|
||||
def copy(self, default=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
self = self.with_context(active_test=False)
|
||||
if not default.get('name'):
|
||||
default['name'] = _("%s (copy)") % (self.name)
|
||||
project = super(Project, self).copy(default)
|
||||
|
||||
@@ -731,7 +731,7 @@
|
||||
<field name="name">Project's tasks</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar,graph,kanban</field>
|
||||
<field name="domain">[('project_id', 'child_of', [active_id])]</field>
|
||||
<field name="domain">[('project_id', '=', active_id)]</field>
|
||||
<field name="context">{'project_id':active_id}</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ class TestCreatePicking(common.TestProductCommon):
|
||||
'route_ids': [(4, self.ref('stock.route_warehouse0_mto')), (4, self.ref('purchase.route_warehouse0_buy'))],
|
||||
'seller_ids': [(6, 0, [seller.id])],
|
||||
'categ_id': self.env.ref('product.product_category_all').id,
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
})
|
||||
|
||||
customer_move = self.env['stock.move'].create({
|
||||
|
||||
@@ -218,6 +218,7 @@
|
||||
</tree>
|
||||
<form string="Purchase Order Line">
|
||||
<sheet>
|
||||
<field name="state" invisible="1"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id"
|
||||
|
||||
@@ -24,7 +24,7 @@ class MailController(MailController):
|
||||
except AccessError:
|
||||
if record_sudo.access_token and consteq(record_sudo.access_token, access_token):
|
||||
record_action = record_sudo.with_context(
|
||||
force_website=True).get_access_action(uid)
|
||||
force_website=True).get_access_action()
|
||||
if record_action['type'] == 'ir.actions.act_url':
|
||||
return werkzeug.utils.redirect(record_action['url'])
|
||||
return super(MailController, cls)._redirect_to_record(model, res_id, access_token=access_token)
|
||||
|
||||
@@ -30,7 +30,7 @@ class PaymentPortal(http.Controller):
|
||||
# we check if the order need to create a payment token
|
||||
save_token = save_token or order_sudo._get_payment_type() == "form_save"
|
||||
|
||||
if request.env.user == request.env.ref('base.public_user'):
|
||||
if request.env.user._is_public():
|
||||
save_token = False
|
||||
|
||||
token = request.env['payment.token'].sudo() # currently no support of payment tokens
|
||||
@@ -74,7 +74,7 @@ class PaymentPortal(http.Controller):
|
||||
except (ValueError, TypeError):
|
||||
token = False
|
||||
|
||||
token_owner = order_sudo.partner_id if request.env.user == request.env.ref('base.public_user') else request.env.user.partner_id
|
||||
token_owner = order_sudo.partner_id if request.env.user._is_public() else request.env.user.partner_id
|
||||
if not token or token.partner_id != token_owner:
|
||||
params['error'] = 'pay_sale_invalid_token'
|
||||
return request.redirect(_build_url_w_params(error_url, params))
|
||||
|
||||
@@ -12,7 +12,7 @@ class CustomerPortal(CustomerPortal):
|
||||
if values['portal_confirmation'] == 'pay':
|
||||
payment_inputs = request.env['payment.acquirer']._get_available_payment_input(order.partner_id, order.company_id)
|
||||
# if not connected (using public user), the method _get_available_payment_input will return public user tokens
|
||||
is_public_user = request.env.ref('base.public_user') == request.env.user
|
||||
is_public_user = request.env.user._is_public()
|
||||
if is_public_user:
|
||||
# we should not display payment tokens owned by the public user
|
||||
payment_inputs.pop('pms', None)
|
||||
|
||||
@@ -235,7 +235,10 @@ class SaleOrderLine(models.Model):
|
||||
return {}
|
||||
if self.product_id.type == 'product':
|
||||
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
product = self.product_id.with_context(warehouse=self.order_id.warehouse_id.id)
|
||||
product = self.product_id.with_context(
|
||||
warehouse=self.order_id.warehouse_id.id,
|
||||
lang=self.order_id.partner_id.lang or self.env.user.lang or 'en_US'
|
||||
)
|
||||
product_qty = self.product_uom._compute_quantity(self.product_uom_qty, self.product_id.uom_id)
|
||||
if float_compare(product.virtual_available, product_qty, precision_digits=precision) == -1:
|
||||
is_available = self._check_routing()
|
||||
|
||||
@@ -14,26 +14,31 @@
|
||||
<field name="location_id" ref="stock_location_suppliers"/>
|
||||
<field name="usage">supplier</field>
|
||||
<field name="barcode">2601985</field>
|
||||
<field name="company_id"></field>
|
||||
</record>
|
||||
<record id="stock_location_4" model="stock.location">
|
||||
<field name="name">Big Vendors</field>
|
||||
<field name="location_id" ref="stock_location_3"/>
|
||||
<field name="usage">supplier</field>
|
||||
<field name="company_id"></field>
|
||||
</record>
|
||||
<record id="stock_location_5" model="stock.location">
|
||||
<field name="name">Generic IT Vendors</field>
|
||||
<field name="location_id" ref="stock_location_3"/>
|
||||
<field name="usage">supplier</field>
|
||||
<field name="company_id"></field>
|
||||
</record>
|
||||
<record id="stock_location_7" model="stock.location">
|
||||
<field name="name">European Customers</field>
|
||||
<field name="location_id" ref="stock_location_customers"/>
|
||||
<field name="usage">customer</field>
|
||||
<field name="company_id"></field>
|
||||
</record>
|
||||
<record id="stock_location_8" model="stock.location">
|
||||
<field name="name">Non European Customers</field>
|
||||
<field name="location_id" ref="stock_location_customers"/>
|
||||
<field name="usage">customer</field>
|
||||
<field name="company_id"></field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
@@ -3332,6 +3332,11 @@ msgstr ""
|
||||
msgid "One product only"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock
|
||||
#: model:ir.ui.view,arch_db:stock.view_quant_package_form
|
||||
msgid "Ongoing Package Creation: Content"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock
|
||||
#: model:ir.model.fields,field_description:stock.field_stock_location_path__name
|
||||
msgid "Operation Name"
|
||||
|
||||
@@ -159,7 +159,7 @@ class Product(models.Model):
|
||||
if self.env.context.get('company_owned', False):
|
||||
company_id = self.env.user.company_id.id
|
||||
return (
|
||||
[('location_id.company_id', '=', company_id)],
|
||||
[('location_id.company_id', '=', company_id), ('location_id.usage', 'in', ['internal', 'transit'])],
|
||||
[('location_id.company_id', '=', False), ('location_dest_id.company_id', '=', company_id)],
|
||||
[('location_id.company_id', '=', company_id), ('location_dest_id.company_id', '=', False),
|
||||
])
|
||||
|
||||
@@ -1033,7 +1033,7 @@ class StockMove(models.Model):
|
||||
if move.propagate:
|
||||
# only cancel the next move if all my siblings are also cancelled
|
||||
if all(state == 'cancel' for state in siblings_states):
|
||||
move.move_dest_ids._action_cancel()
|
||||
move.move_dest_ids.filtered(lambda m: m.state != 'done')._action_cancel()
|
||||
else:
|
||||
if all(state in ('done', 'cancel') for state in siblings_states):
|
||||
move.move_dest_ids.write({'procure_method': 'make_to_stock'})
|
||||
@@ -1043,6 +1043,7 @@ class StockMove(models.Model):
|
||||
|
||||
def _prepare_extra_move_vals(self, qty):
|
||||
vals = {
|
||||
'origin_returned_move_id': self.origin_returned_move_id.id,
|
||||
'product_uom_qty': qty,
|
||||
'picking_id': self.picking_id.id,
|
||||
'price_unit': self.price_unit,
|
||||
@@ -1098,8 +1099,7 @@ class StockMove(models.Model):
|
||||
|
||||
def _action_done(self):
|
||||
self.filtered(lambda move: move.state == 'draft')._action_confirm() # MRP allows scrapping draft moves
|
||||
|
||||
moves = self.filtered(lambda x: x.state not in ('done', 'cancel'))
|
||||
moves = self.exists().filtered(lambda x: x.state not in ('done', 'cancel'))
|
||||
moves_todo = self.env['stock.move']
|
||||
|
||||
# Cancel moves where necessary ; we should do it before creating the extra moves because
|
||||
|
||||
@@ -460,7 +460,7 @@ class QuantPackage(models.Model):
|
||||
return action
|
||||
|
||||
def _get_contained_quants(self):
|
||||
return self.env['stock.quant'].search([('package_id', 'child_of', self.ids)])
|
||||
return self.env['stock.quant'].search([('package_id', 'in', self.ids)])
|
||||
|
||||
def _get_all_products_quantities(self):
|
||||
'''This function computes the different product quantities for the given package
|
||||
|
||||
@@ -185,6 +185,30 @@ class TestPickShip(TestStockCommon):
|
||||
# the client picking should not be assigned anymore, as we returned partially what we took
|
||||
self.assertEqual(picking_client.state, 'confirmed')
|
||||
|
||||
def test_mto_moves_return_extra(self):
|
||||
picking_pick, picking_client = self.create_pick_ship()
|
||||
stock_location = self.env['stock.location'].browse(self.stock_location)
|
||||
self.env['stock.quant']._update_available_quantity(self.productA, stock_location, 10.0)
|
||||
|
||||
picking_pick.action_assign()
|
||||
picking_pick.move_lines[0].move_line_ids[0].qty_done = 10.0
|
||||
picking_pick.action_done()
|
||||
self.assertEqual(picking_pick.state, 'done')
|
||||
self.assertEqual(picking_client.state, 'assigned')
|
||||
|
||||
# return more than we've done
|
||||
stock_return_picking = self.env['stock.return.picking']\
|
||||
.with_context(active_ids=picking_pick.ids, active_id=picking_pick.ids[0])\
|
||||
.create({})
|
||||
stock_return_picking.product_return_moves.quantity = 12.0 # Return 2 extra
|
||||
stock_return_picking_action = stock_return_picking.create_returns()
|
||||
return_pick = self.env['stock.picking'].browse(stock_return_picking_action['res_id'])
|
||||
|
||||
# Verify the extra move has been merged with the original move
|
||||
self.assertAlmostEqual(return_pick.move_lines.product_uom_qty, 12.0)
|
||||
self.assertAlmostEqual(return_pick.move_lines.quantity_done, 0.0)
|
||||
self.assertAlmostEqual(return_pick.move_lines.reserved_availability, 10.0)
|
||||
|
||||
def test_mto_resupply_cancel_ship(self):
|
||||
""" This test simulates a pick pack ship with a resupply route
|
||||
set. Pick and pack are validated, ship is cancelled. This test
|
||||
|
||||
@@ -62,7 +62,7 @@ class TestWarehouse(TestStockCommon):
|
||||
# Check inventory obj details (1 inventory with 1 line, because 1 product change)
|
||||
inventory = self.env['stock.inventory'].search([('id', 'not in', self.existing_inventories.ids)])
|
||||
self.assertEqual(len(inventory), 1)
|
||||
self.assertIn('INV: %s' % self.product_1.name, inventory.name)
|
||||
self.assertIn('INV: %s' % self.product_1.display_name, inventory.name)
|
||||
self.assertEqual(len(inventory.line_ids), 1)
|
||||
self.assertEqual(inventory.line_ids.product_id, self.product_1)
|
||||
self.assertEqual(inventory.line_ids.product_qty, 50.0)
|
||||
@@ -457,4 +457,4 @@ class TestResupply(TestStockCommon):
|
||||
'product_min_qty': 10,
|
||||
'product_max_qty': 100,
|
||||
'product_uom': self.uom_unit.id,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
<field name="location_id"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Content" />
|
||||
<separator string="Ongoing Package Creation: Content" attrs="{'invisible': [('current_picking_id', '=', False)]}"/>
|
||||
<field name="current_picking_id" invisible="1"/>
|
||||
<field name="current_picking_move_line_ids" readonly="1" attrs="{'invisible': [('current_picking_id', '=', False)]}">
|
||||
<tree>
|
||||
@@ -201,6 +201,7 @@
|
||||
<field name="product_uom_id" groups="uom.group_uom"/>
|
||||
</tree>
|
||||
</field>
|
||||
<separator string="Content" attrs="{'invisible': [('current_picking_id', '=', True)]}"/>
|
||||
<field name="quant_ids" attrs="{'invisible': [('current_picking_id', '=', True)]}">
|
||||
<tree>
|
||||
<field name="product_id"/>
|
||||
|
||||
@@ -383,7 +383,8 @@ class StockMove(models.Model):
|
||||
qty_done = 0.0
|
||||
if float_is_zero(product_tot_qty_available, precision_rounding=rounding):
|
||||
new_std_price = move._get_price_unit()
|
||||
elif float_is_zero(product_tot_qty_available + move.product_qty, precision_rounding=rounding):
|
||||
elif float_is_zero(product_tot_qty_available + move.product_qty, precision_rounding=rounding) or \
|
||||
float_is_zero(product_tot_qty_available + qty_done, precision_rounding=rounding):
|
||||
new_std_price = move._get_price_unit()
|
||||
else:
|
||||
# Get the standard price
|
||||
|
||||
@@ -3144,7 +3144,7 @@ class TestStockValuation(TransactionCase):
|
||||
self.assertEqual(move1.remaining_value, 10)
|
||||
self.assertEqual(move1.remaining_qty, 1)
|
||||
self.assertAlmostEqual(self.product1.qty_available, 0.0)
|
||||
self.assertAlmostEqual(self.product1.qty_at_date, 2.0)
|
||||
self.assertAlmostEqual(self.product1.qty_at_date, 1.0)
|
||||
self.assertEqual(self.product1.stock_value, 10)
|
||||
self.assertTrue(len(move1.account_move_ids), 1)
|
||||
|
||||
|
||||
@@ -107,9 +107,9 @@ class LandedCost(models.Model):
|
||||
new_landed_cost_value = line.move_id.landed_cost_value + line.additional_landed_cost
|
||||
line.move_id.write({
|
||||
'landed_cost_value': new_landed_cost_value,
|
||||
'value': line.move_id.value + cost_to_add,
|
||||
'value': line.move_id.value + line.additional_landed_cost,
|
||||
'remaining_value': line.move_id.remaining_value + cost_to_add,
|
||||
'price_unit': (line.move_id.value + cost_to_add) / line.move_id.product_qty,
|
||||
'price_unit': (line.move_id.value + line.additional_landed_cost) / line.move_id.product_qty,
|
||||
})
|
||||
# `remaining_qty` is negative if the move is out and delivered proudcts that were not
|
||||
# in stock.
|
||||
|
||||
@@ -243,5 +243,293 @@ response = request.render("website.template_partner_comment", {
|
||||
<field name="website_id" ref="website2"/>
|
||||
<field name="page_id" ref="website2_contactus_page" />
|
||||
</record>
|
||||
|
||||
<!-- BS Debug Page -->
|
||||
<!-- Showcase all (most?) BS components and utilities -->
|
||||
<record id="bs_debug_page" model="website.page">
|
||||
<field name="name">BS Debug</field>
|
||||
<field name="url">/website/demo/bootstrap</field>
|
||||
<field name="website_published">False</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">website.bs_debug_page_view</field>
|
||||
<field name="arch" type="xml">
|
||||
<t name="Debug" t-name="website.bs_debug_page_view">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="odoo_theme_colors" t-value="[['alpha', 'Alpha'], ['beta', 'Beta'], ['gamma', 'Gamma'], ['delta', 'Delta'], ['epsilon', 'Epsilon']]"/>
|
||||
<t t-set="bs_basic_colors" t-value="[['primary', 'Primary'], ['default', 'Default']]"/>
|
||||
<t t-set="bs_state_colors" t-value="[['success', 'Success'], ['info', 'Info'], ['warning', 'Warning'], ['danger', 'Danger']]"/>
|
||||
<t t-set="bs_theme_colors" t-value="bs_basic_colors + bs_state_colors"/>
|
||||
<t t-set="bs_gray_colors" t-value="[['white', 'White'], ['gray-lighter', 'Gray Lighter'], ['gray-light', 'Gray Light'], ['gray', 'Gray'], ['gray-dark', 'Gray Dark'], ['gray-darker', 'Gray Darker'], ['black', 'Black']]"/>
|
||||
<div id="wrap oe_structure">
|
||||
<section class="py-2">
|
||||
<div class="container">
|
||||
<h1>Components</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<h2>Badge</h2>
|
||||
<span class="badge mb4">This is a badge</span>
|
||||
|
||||
<h2 class="mt8">Label</h2>
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<span t-attf-class="label mb4 label-#{color[0]}"><t t-esc="color[1]"/></span>
|
||||
</t>
|
||||
<h3 class="mt8 h5">Link</h3>
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<a href="#" t-attf-class="label mb4 label-#{color[0]}"><t t-esc="color[1]"/></a>
|
||||
</t>
|
||||
<h3 class="mt8 h5">Autosizing</h3>
|
||||
<div class="mt0 h3">
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<span t-attf-class="label mb4 label-#{color[0]}"><t t-esc="color[1]"/></span>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<h2 class="mt16">Button</h2>
|
||||
<t t-foreach="odoo_theme_colors" t-as="color">
|
||||
<button type="button" t-attf-class="btn mb4 btn-#{color[0]}"><t t-esc="color[1]"/></button>
|
||||
</t>
|
||||
<br/>
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<button type="button" t-attf-class="btn mb4 btn-#{color[0]}"><t t-esc="color[1]"/></button>
|
||||
</t>
|
||||
<h3 class="mt8 h6">Extra Small</h3>
|
||||
<t t-foreach="odoo_theme_colors" t-as="color">
|
||||
<button type="button" t-attf-class="btn mb4 btn-xs btn-#{color[0]}"><t t-esc="color[1]"/></button>
|
||||
</t>
|
||||
<br/>
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<button type="button" t-attf-class="btn mb4 btn-xs btn-#{color[0]}"><t t-esc="color[1]"/></button>
|
||||
</t>
|
||||
<h3 class="mt8 h5">Small</h3>
|
||||
<t t-foreach="odoo_theme_colors" t-as="color">
|
||||
<button type="button" t-attf-class="btn mb4 btn-sm btn-#{color[0]}"><t t-esc="color[1]"/></button>
|
||||
</t>
|
||||
<br/>
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<button type="button" t-attf-class="btn mb4 btn-sm btn-#{color[0]}"><t t-esc="color[1]"/></button>
|
||||
</t>
|
||||
<h3 class="mt8 h5">Large</h3>
|
||||
<t t-foreach="odoo_theme_colors" t-as="color">
|
||||
<button type="button" t-attf-class="btn mb4 btn-lg btn-#{color[0]}"><t t-esc="color[1]"/></button>
|
||||
</t>
|
||||
<br/>
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<button type="button" t-attf-class="btn mb4 btn-lg btn-#{color[0]}"><t t-esc="color[1]"/></button>
|
||||
</t>
|
||||
|
||||
<h2 class="mt16">Dropdown</h2>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">Toggle <span class="caret"/></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="dropdown-header">Header</li>
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li class="divider"/>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 class="mt16">Navbar</h2>
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="#">Navbar</a>
|
||||
<button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active">
|
||||
<a href="#">Home <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">Link</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="disabled" href="#">Disabled</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="navbar-form navbar-right">
|
||||
<input class="form-control" type="search" placeholder="Search" aria-label="Search"/>
|
||||
<button class="btn btn-success" type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<h2 class="mt16">Form</h2>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Email address</label>
|
||||
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email"/>
|
||||
<small id="emailHelp" class="help-block text-muted">We'll never share your email with anyone else.</small>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h2 class="mt16">Pagination</h2>
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
<li class="disabled">
|
||||
<a href="#" tabindex="-1">Previous</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">1</a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<a href="#">2 <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">3</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">Next</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h2>Alert</h2>
|
||||
<t t-foreach="bs_state_colors" t-as="color">
|
||||
<div t-attf-class="alert alert-#{color[0]}">
|
||||
This is a "<t t-esc="color[1]"/>" alert with a <a href="#" class="alert-link">link</a>.
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<h2 class="mt16">Breadcrumb</h2>
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="#">Home</a></li>
|
||||
<li><a href="#">Library</a></li>
|
||||
<li class="active" aria-current="page">Data</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<h2 class="mt16">Card</h2>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Card Header
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Card Body
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">Item 1</li>
|
||||
<li class="list-group-item">Item 2</li>
|
||||
</ul>
|
||||
<div class="panel-footer">
|
||||
Card Footer
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="py-2">
|
||||
<div class="container">
|
||||
<h1>Utilities & Typography</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<div>
|
||||
<t t-foreach="odoo_theme_colors" t-as="color">
|
||||
<div t-attf-class="bg-#{color[0]}" style="display: inline-block; padding: 4px 12px;">
|
||||
<t t-esc="color[1]"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mt8">
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<div t-attf-class="bg-#{color[0]}" style="display: inline-block; padding: 4px 12px;">
|
||||
<t t-esc="color[1]"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mt8">
|
||||
<t t-foreach="bs_gray_colors" t-as="color">
|
||||
<div t-attf-class="bg-#{color[0]}" style="display: inline-block; padding: 4px 12px;">
|
||||
<t t-esc="color[1]"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mt16">
|
||||
<t t-foreach="odoo_theme_colors" t-as="color">
|
||||
<div t-attf-class="text-#{color[0]}" style="display: inline-block; padding: 4px 12px;">
|
||||
<t t-esc="color[1]"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mt8">
|
||||
<t t-foreach="bs_theme_colors" t-as="color">
|
||||
<div t-attf-class="text-#{color[0]}" style="display: inline-block; padding: 4px 12px;">
|
||||
<t t-esc="color[1]"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mt8">
|
||||
<t t-foreach="bs_gray_colors" t-as="color">
|
||||
<div t-attf-class="text-#{color[0]}" style="display: inline-block; padding: 4px 12px;">
|
||||
<t t-esc="color[1]"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h1>Headings 1</h1>
|
||||
<h2>Headings 2</h2>
|
||||
<h3>Headings 3</h3>
|
||||
<h4>Headings 4</h4>
|
||||
<h5>Headings 5</h5>
|
||||
<h6>Headings 6</h6>
|
||||
<p>Paragraph with <strong>bold</strong>, <span class="text-muted">muted</span> and <em>italic</em> texts</p>
|
||||
<p><a href="#">Link</a></p>
|
||||
<p><button type="button" class="btn btn-link">Link button</button></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Snippet Debug Page -->
|
||||
<!-- Showcase all snippets -->
|
||||
<record id="snippets_debug_page" model="website.page">
|
||||
<field name="name">Snippet Debug</field>
|
||||
<field name="url">/website/demo/snippets</field>
|
||||
<field name="website_published">False</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">website.snippets_debug_page_view</field>
|
||||
<field name="arch" type="xml">
|
||||
<t name="Debug" t-name="website.snippets_debug_page_view">
|
||||
<t t-call="website.layout">
|
||||
<style>
|
||||
#snippets_menu, #o_scroll > .o_panel > .o_panel_header {
|
||||
display: none !important;
|
||||
}
|
||||
[data-oe-type="snippet"]:not([data-module-id])::before {
|
||||
content: attr(name);
|
||||
display: block;
|
||||
padding: 16px;
|
||||
background-color: lightgray;
|
||||
color: black;
|
||||
font-size: 24px;
|
||||
}
|
||||
[data-oe-type="snippet"]:not([data-module-id])::after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
</style>
|
||||
<div id="wrap oe_structure">
|
||||
<t t-call="website.snippets"/>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -699,6 +699,7 @@ registry.gallery = Animation.extend({
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onClickImg: function (ev) {
|
||||
var self = this;
|
||||
var $cur = $(ev.currentTarget);
|
||||
|
||||
var urls = [];
|
||||
@@ -743,7 +744,12 @@ registry.gallery = Animation.extend({
|
||||
$modal.find('.modal-content, .modal-body.o_slideshow').css('height', '100%');
|
||||
$modal.appendTo(document.body);
|
||||
|
||||
this.carousel = new registry.gallery_slider($modal.find('.carousel').carousel());
|
||||
$modal.one('shown.bs.modal', function () {
|
||||
self.trigger_up('animation_start_demand', {
|
||||
editableMode: false,
|
||||
$target: $modal.find('.modal-body.o_slideshow'),
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -411,30 +411,27 @@ div.carousel .container {
|
||||
border-width: 0;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
left: 0%;
|
||||
|
||||
> * {
|
||||
list-style-image: none;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 0px 5px 5px;
|
||||
margin: 2.5px 2.5px 2.5px 2.5px;
|
||||
padding: 0;
|
||||
border: 1px solid #aaa;
|
||||
text-indent: initial;
|
||||
background-size: cover;
|
||||
background-color: #fff;
|
||||
border-radius: 0;
|
||||
vertical-align: bottom;
|
||||
|
||||
&:not(.active) {
|
||||
opacity: 0.8;
|
||||
-webkit-filter: grayscale(100%);
|
||||
filter: grayscale(100%);
|
||||
filter: gray;
|
||||
filter: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' /></filter></svg>#greyscale");
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
filter: grayscale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,6 +441,12 @@ div.carousel .container {
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
&.left * {
|
||||
right: 0%;
|
||||
}
|
||||
&.right * {
|
||||
left: 0%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
</div>
|
||||
|
||||
<ul class="carousel-indicators">
|
||||
<li class="fa fa-chevron-left o_indicators_left" style="overflow: hidden; padding: 12px; border: 0;"></li>
|
||||
<li class="fa fa-chevron-left o_indicators_left" style="overflow: hidden; padding: 12px; border: 0; visibility: hidden;"></li>
|
||||
<t t-foreach="srcs" t-as="src">
|
||||
<li t-attf-data-target="##{id}" t-att-data-slide-to="src_index" t-att-class="src_index == index and 'active'" t-attf-style="background-image: url(#{src})"></li>
|
||||
<li t-attf-data-target="##{id}" t-att-data-slide-to="src_index" t-att-class="'hidden ' + (src_index == index and 'active')" t-attf-style="background-image: url(#{src})"></li>
|
||||
</t>
|
||||
<li class="fa fa-chevron-right o_indicators_right" style="overflow: hidden; padding: 12px; border: 0;"></li>
|
||||
<li class="fa fa-chevron-right o_indicators_right" style="overflow: hidden; padding: 12px; border: 0; visibility: hidden;"></li>
|
||||
</ul>
|
||||
|
||||
<a class="carousel-control left" t-attf-href="##{id}" data-slide="prev"><span class="fa fa-chevron-left" /></a>
|
||||
|
||||
@@ -26,7 +26,7 @@ class Event(models.Model):
|
||||
|
||||
def _compute_is_participating(self):
|
||||
# we don't allow public user to see participating label
|
||||
if self.env.user != self.env.ref('base.public_user'):
|
||||
if not self.env.user._is_public():
|
||||
email = self.env.user.partner_id.email
|
||||
for event in self:
|
||||
domain = ['&', '|', ('email', '=', email), ('partner_id', '=', self.env.user.partner_id.id), ('event_id', '=', event.id)]
|
||||
|
||||
@@ -17,8 +17,9 @@ class SaleOrder(models.Model):
|
||||
_inherit = "sale.order"
|
||||
|
||||
website_order_line = fields.One2many(
|
||||
'sale.order.line', 'order_id',
|
||||
string='Order Lines displayed on Website', readonly=True,
|
||||
'sale.order.line',
|
||||
compute='_compute_website_order_line',
|
||||
string='Order Lines displayed on Website',
|
||||
help='Order Lines to be displayed on the website. They should not be used for computation purpose.',
|
||||
)
|
||||
cart_quantity = fields.Integer(compute='_compute_cart_info', string='Cart Quantity')
|
||||
@@ -36,6 +37,10 @@ class SaleOrder(models.Model):
|
||||
for order in self:
|
||||
order.can_directly_mark_as_paid = order.state in ['sent', 'sale'] and order.payment_tx_id and order.payment_acquirer_id.provider in ['transfer', 'manual']
|
||||
|
||||
@api.one
|
||||
def _compute_website_order_line(self):
|
||||
self.website_order_line = self.order_line
|
||||
|
||||
@api.multi
|
||||
@api.depends('website_order_line.product_uom_qty', 'website_order_line.product_id')
|
||||
def _compute_cart_info(self):
|
||||
|
||||
@@ -168,7 +168,7 @@ class Website(models.Model):
|
||||
'partner_id': partner.id,
|
||||
'pricelist_id': pricelist.id,
|
||||
'payment_term_id': self.sale_get_payment_term(partner),
|
||||
'team_id': self.salesteam_id.id,
|
||||
'team_id': self.salesteam_id.id or partner.parent_id.team_id.id or partner.team_id.id,
|
||||
'partner_invoice_id': addr['invoice'],
|
||||
'partner_shipping_id': addr['delivery'],
|
||||
'user_id': salesperson_id or self.salesperson_id.id or default_user_id,
|
||||
|
||||
@@ -17,11 +17,11 @@ class SaleOrder(models.Model):
|
||||
has_delivery = fields.Boolean(
|
||||
compute='_compute_has_delivery', string='Has delivery',
|
||||
help="Has an order line set for delivery", store=True)
|
||||
website_order_line = fields.One2many(
|
||||
'sale.order.line', 'order_id',
|
||||
string='Order Lines displayed on Website', readonly=True,
|
||||
domain=[('is_delivery', '=', False)],
|
||||
help='Order Lines to be displayed on the website. They should not be used for computation purpose.')
|
||||
|
||||
@api.one
|
||||
def _compute_website_order_line(self):
|
||||
super(SaleOrder, self)._compute_website_order_line()
|
||||
self.website_order_line = self.website_order_line.filtered(lambda l: not l.is_delivery)
|
||||
|
||||
@api.depends('order_line.price_unit', 'order_line.tax_id', 'order_line.discount', 'order_line.product_uom_qty')
|
||||
def _compute_amount_delivery(self):
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
India, 2018-09-18
|
||||
|
||||
Dreambits Technologies Pvt. Ltd. agrees to the terms of the Odoo Corporate Contributor License
|
||||
Agreement v1.0.
|
||||
|
||||
I declare that I am authorized and able to make this agreement and sign this
|
||||
declaration.
|
||||
|
||||
Signed,
|
||||
|
||||
Karan Shah admin@dreambits.in https://github.com/karan-dreambits
|
||||
|
||||
List of contributors:
|
||||
|
||||
Karan Shah admin@dreambits.in https://github.com/karan-dreambits
|
||||
Devang Pipaliya devang@dreambits.in https://github.com/devang-dreambits
|
||||
@@ -56,7 +56,7 @@ Running the server
|
||||
Maximum allowed virtual memory per worker. If the limit is exceeded,
|
||||
the worker is killed and recycled at the end of the current request.
|
||||
|
||||
Defaults to 2048MB.
|
||||
Defaults to 2048MiB.
|
||||
|
||||
.. option:: --limit-memory-hard <limit>
|
||||
|
||||
@@ -64,7 +64,7 @@ Running the server
|
||||
immediately killed without waiting for the end of the current request
|
||||
processing.
|
||||
|
||||
Defaults to 2560MB.
|
||||
Defaults to 2560MiB.
|
||||
|
||||
.. option:: --limit-time-cpu <limit>
|
||||
|
||||
|
||||
@@ -653,6 +653,7 @@
|
||||
<field file="base/static/img/country_flags/gt.png" name="image" type="base64" />
|
||||
<field name="currency_id" ref="GTQ" />
|
||||
<field eval="502" name="phone_code" />
|
||||
<field name="vat_label">NIT</field>
|
||||
</record>
|
||||
<record id="gu" model="res.country">
|
||||
<field name="name">Guam</field>
|
||||
@@ -1127,6 +1128,7 @@
|
||||
<field name="currency_id" ref="MXN" />
|
||||
<field eval="52" name="phone_code" />
|
||||
<field name="vat_label">RFC</field>
|
||||
<field eval="'%(street)s %(street2)s\n%(zip)s %(city)s, %(state_code)s\n%(country_name)s'" name="address_format" />
|
||||
</record>
|
||||
<record id="my" model="res.country">
|
||||
<field name="name">Malaysia</field>
|
||||
@@ -1732,6 +1734,7 @@
|
||||
<field file="base/static/img/country_flags/vn.png" name="image" type="base64" />
|
||||
<field name="currency_id" ref="VND" />
|
||||
<field eval="84" name="phone_code" />
|
||||
<field eval="'%(street)s\n%(street2)s\n%(city)s\n%(name)s %(zip)s %(country_name)s'" name="address_format" />
|
||||
</record>
|
||||
<record id="vu" model="res.country">
|
||||
<field name="name">Vanuatu</field>
|
||||
|
||||
@@ -562,6 +562,9 @@ class IrActionsServer(models.Model):
|
||||
active_id = self._context.get('active_id')
|
||||
if not active_id and self._context.get('onchange_self'):
|
||||
active_id = self._context['onchange_self']._origin.id
|
||||
if not active_id: # onchange on new record
|
||||
func = getattr(self, 'run_action_%s' % action.state)
|
||||
res = func(action, eval_context=eval_context)
|
||||
active_ids = self._context.get('active_ids', [active_id] if active_id else [])
|
||||
for active_id in active_ids:
|
||||
# run context dedicated to a particular active_id
|
||||
|
||||
@@ -285,10 +285,12 @@ class configmanager(object):
|
||||
help="Specify the number of workers, 0 disable prefork mode.",
|
||||
type="int")
|
||||
group.add_option("--limit-memory-soft", dest="limit_memory_soft", my_default=2048 * 1024 * 1024,
|
||||
help="Maximum allowed virtual memory per worker, when reached the worker be reset after the current request (default 671088640 aka 640MB).",
|
||||
help="Maximum allowed virtual memory per worker, when reached the worker be "
|
||||
"reset after the current request (default 2048MiB).",
|
||||
type="int")
|
||||
group.add_option("--limit-memory-hard", dest="limit_memory_hard", my_default=2560 * 1024 * 1024,
|
||||
help="Maximum allowed virtual memory per worker, when reached, any memory allocation will fail (default 805306368 aka 768MB).",
|
||||
help="Maximum allowed virtual memory per worker, when reached, any memory "
|
||||
"allocation will fail (default 2560MiB).",
|
||||
type="int")
|
||||
group.add_option("--limit-time-cpu", dest="limit_time_cpu", my_default=60,
|
||||
help="Maximum allowed CPU time per request (default 60).",
|
||||
|
||||
Reference in New Issue
Block a user