[MERGE] forward port of branch 8.0 up to bff6dff
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import fields, osv, expression
|
||||
from openerp.tools import float_is_zero
|
||||
from openerp.tools.translate import _
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.report import report_sxw
|
||||
@@ -597,7 +598,7 @@ class account_bank_statement_line(osv.osv):
|
||||
domain += [(amount_field, '<', 0), (amount_field, '>', (sign * amount))]
|
||||
else:
|
||||
domain += [(amount_field, '>', 0), (amount_field, '<', (sign * amount))]
|
||||
mv_lines = self.get_move_lines_for_reconciliation(cr, uid, st_line, excluded_ids=excluded_ids, limit=5, additional_domain=domain)
|
||||
mv_lines = self.get_move_lines_for_reconciliation(cr, uid, st_line, excluded_ids=excluded_ids, limit=5, additional_domain=domain, context=context)
|
||||
ret = []
|
||||
total = 0
|
||||
for line in mv_lines:
|
||||
@@ -841,6 +842,11 @@ class account_bank_statement_line(osv.osv):
|
||||
if mv_line_dict.get('counterpart_move_line_id'):
|
||||
#post an account line that use the same currency rate than the counterpart (to balance the account) and post the difference in another line
|
||||
ctx['date'] = mv_line.date
|
||||
if mv_line.currency_id.id == mv_line_dict['currency_id'] \
|
||||
and float_is_zero(abs(mv_line.amount_currency) - abs(mv_line_dict['amount_currency']), precision_rounding=mv_line.currency_id.rounding):
|
||||
debit_at_old_rate = mv_line.credit
|
||||
credit_at_old_rate = mv_line.debit
|
||||
else:
|
||||
debit_at_old_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['debit'], context=ctx)
|
||||
credit_at_old_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['credit'], context=ctx)
|
||||
mv_line_dict['credit'] = credit_at_old_rate
|
||||
|
||||
@@ -131,7 +131,7 @@ class account_invoice(models.Model):
|
||||
continue
|
||||
# Get the correct line residual amount
|
||||
if line.currency_id == self.currency_id:
|
||||
line_amount = line.currency_id and line.amount_residual_currency or line.amount_residual
|
||||
line_amount = line.amount_residual_currency if line.currency_id else line.amount_residual
|
||||
else:
|
||||
from_currency = line.company_id.currency_id.with_context(date=line.date)
|
||||
line_amount = from_currency.compute(line.amount_residual, self.currency_id)
|
||||
|
||||
@@ -867,12 +867,17 @@ class account_move_line(osv.osv):
|
||||
total_amount_currency_str = rml_parser.formatLang(total_amount, currency_obj=line_currency)
|
||||
ret_line['credit_currency'] = actual_credit
|
||||
ret_line['debit_currency'] = actual_debit
|
||||
ctx = context.copy()
|
||||
if target_date:
|
||||
ctx.update({'date': target_date})
|
||||
total_amount = currency_obj.compute(cr, uid, line_currency.id, target_currency.id, total_amount, context=ctx)
|
||||
actual_debit = currency_obj.compute(cr, uid, line_currency.id, target_currency.id, actual_debit, context=ctx)
|
||||
actual_credit = currency_obj.compute(cr, uid, line_currency.id, target_currency.id, actual_credit, context=ctx)
|
||||
if target_currency == company_currency:
|
||||
actual_debit = debit
|
||||
actual_credit = credit
|
||||
total_amount = debit or credit
|
||||
else:
|
||||
ctx = context.copy()
|
||||
if target_date:
|
||||
ctx.update({'date': target_date})
|
||||
total_amount = currency_obj.compute(cr, uid, line_currency.id, target_currency.id, total_amount, context=ctx)
|
||||
actual_debit = currency_obj.compute(cr, uid, line_currency.id, target_currency.id, actual_debit, context=ctx)
|
||||
actual_credit = currency_obj.compute(cr, uid, line_currency.id, target_currency.id, actual_credit, context=ctx)
|
||||
amount_str = rml_parser.formatLang(actual_debit or actual_credit, currency_obj=target_currency)
|
||||
total_amount_str = rml_parser.formatLang(total_amount, currency_obj=target_currency)
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ class account_entries_report(osv.osv):
|
||||
l.amount_currency as amount_currency,
|
||||
l.debit as debit,
|
||||
l.credit as credit,
|
||||
l.debit-l.credit as balance
|
||||
coalesce(l.debit, 0.0) - coalesce(l.credit, 0.0) as balance
|
||||
from
|
||||
account_move_line l
|
||||
left join account_account a on (l.account_id = a.id)
|
||||
|
||||
@@ -236,7 +236,7 @@ openerp.account = function (instance) {
|
||||
|
||||
// Display the reconciliations
|
||||
return self.model_bank_statement_line
|
||||
.call("get_data_for_reconciliations", [reconciliations_to_show])
|
||||
.call("get_data_for_reconciliations", [reconciliations_to_show], {context:self.session.user_context})
|
||||
.then(function (data) {
|
||||
var child_promises = [];
|
||||
while ((datum = data.shift()) !== undefined)
|
||||
@@ -1638,7 +1638,7 @@ openerp.account = function (instance) {
|
||||
limit += 1; // Let's fetch 1 more item than requested
|
||||
if (limit > 0) {
|
||||
return self.model_bank_statement_line
|
||||
.call("get_move_lines_for_reconciliation_by_statement_line_id", [self.st_line.id, excluded_ids, self.filter, offset, limit])
|
||||
.call("get_move_lines_for_reconciliation_by_statement_line_id", [self.st_line.id, excluded_ids, self.filter, offset, limit], {context:self.session.user_context})
|
||||
.then(function (lines) {
|
||||
_.each(lines, function(line) { self.decorateMoveLine(line, self.st_line.currency_id) }, self);
|
||||
// If we could fetch 1 more item than what we'll display, that means there are move lines left to be displayed (so we enable the pager)
|
||||
|
||||
@@ -47,8 +47,8 @@ class account_statement_from_invoice_lines(osv.osv_memory):
|
||||
statement_obj = self.pool.get('account.bank.statement')
|
||||
statement_line_obj = self.pool.get('account.bank.statement.line')
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
line_date = time.strftime('%Y-%m-%d')
|
||||
statement = statement_obj.browse(cr, uid, statement_id, context=context)
|
||||
line_date = statement.date
|
||||
|
||||
# for each selected move lines
|
||||
for line in line_obj.browse(cr, uid, line_ids, context=context):
|
||||
|
||||
@@ -702,6 +702,9 @@ class calendar_event(osv.Model):
|
||||
val = pytz.UTC.localize(val)
|
||||
return val.astimezone(timezone)
|
||||
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
timezone = pytz.timezone(context.get('tz') or 'UTC')
|
||||
startdate = pytz.UTC.localize(datetime.strptime(event.start, DEFAULT_SERVER_DATETIME_FORMAT)) # Add "+hh:mm" timezone
|
||||
if not startdate:
|
||||
|
||||
@@ -408,8 +408,8 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Opportunities">
|
||||
<header>
|
||||
<button name="case_mark_won" string="Mark Won" type="object" class="oe_highlight"/>
|
||||
<button name="case_mark_lost" string="Mark Lost" type="object" class="oe_highlight"/>
|
||||
<button name="case_mark_won" string="Mark Won" attrs="{'invisible': [('probability', '=', 100)]}" type="object" class="oe_highlight"/>
|
||||
<button name="case_mark_lost" string="Mark Lost" attrs="{'invisible': [('probability', '=', 100)]}" type="object" class="oe_highlight"/>
|
||||
<field name="stage_id" widget="statusbar" clickable="True"
|
||||
options="{'fold_field': 'fold'}"
|
||||
domain="['&', ('team_ids', '=', team_id), '|', ('type', '=', type), ('type', '=', 'both')]"/>
|
||||
|
||||
@@ -41,7 +41,9 @@ invoices from picking, OpenERP is able to add and compute the shipping line.
|
||||
'views/report_shipping.xml',
|
||||
],
|
||||
'demo': ['delivery_demo.xml'],
|
||||
'test': ['test/delivery_cost.yml'],
|
||||
'test': ['test/delivery_cost.yml',
|
||||
'test/stock_move_values_with_invoice_before_delivery.yml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
-
|
||||
test that the store fields of stock moves are computed with invoice before delivery flow
|
||||
-
|
||||
set a weight on ipod 16GB
|
||||
-
|
||||
!python {model: product.product, id: product.product_product_11}: |
|
||||
self.write({'weight': 0.25, 'weight_net': 0.2})
|
||||
-
|
||||
create a SO with invoice before delivery
|
||||
-
|
||||
!record {model: sale.order, id: sale_prepaid}:
|
||||
partner_id: base.res_partner_18
|
||||
partner_invoice_id: base.res_partner_18
|
||||
partner_shipping_id: base.res_partner_18
|
||||
pricelist_id: product.list0
|
||||
order_policy: 'prepaid'
|
||||
order_line:
|
||||
- name: 'Ipod'
|
||||
product_id: product.product_product_11
|
||||
product_uom_qty: 2
|
||||
product_uos_qty: 2
|
||||
product_uom: product.product_uom_unit
|
||||
price_unit: 750.00
|
||||
carrier_id: normal_delivery_carrier
|
||||
-
|
||||
I add delivery cost in Sale order.
|
||||
-
|
||||
!python {model: sale.order, id: sale_prepaid}: |
|
||||
self.delivery_set()
|
||||
-
|
||||
I confirm the SO.
|
||||
-
|
||||
!workflow {model: sale.order, action: order_confirm, ref: sale_prepaid}
|
||||
-
|
||||
I check that the invoice was created
|
||||
-
|
||||
!python {model: sale.order, id: sale_prepaid}: |
|
||||
assert len(self.invoice_ids) == 1, "Invoice not created."
|
||||
-
|
||||
I confirm the invoice
|
||||
-
|
||||
!python {model: sale.order, id: sale_prepaid}: |
|
||||
invoice = self.invoice_ids[0]
|
||||
invoice.signal_workflow('invoice_open')
|
||||
-
|
||||
I pay the invoice.
|
||||
-
|
||||
!python {model: sale.order, id: sale_prepaid}: |
|
||||
invoice = self.invoice_ids[0]
|
||||
invoice.signal_workflow('invoice_open')
|
||||
journal = self.env['account.journal'].search([('type', '=', 'cash'),
|
||||
('company_id', '=', self.company_id.id)],
|
||||
limit=1)
|
||||
invoice.pay_and_reconcile(
|
||||
invoice.amount_total, ref('account.cash'), ref('account.period_8'),
|
||||
journal.id, ref('account.cash'),
|
||||
ref('account.period_8'), journal.id,
|
||||
name='test')
|
||||
-
|
||||
Check the SO after paying the invoice
|
||||
-
|
||||
!python {model: sale.order, id: sale_prepaid}: |
|
||||
assert self.invoice_exists, 'order not invoiced'
|
||||
assert self.invoiced, 'order is not paid'
|
||||
assert len(self.picking_ids) == 1, 'pickings not generated'
|
||||
-
|
||||
check the stock moves
|
||||
-
|
||||
!python {model: sale.order, id: sale_prepaid}: |
|
||||
move = self.picking_ids.move_lines
|
||||
assert move.product_qty == 2, 'wrong product_qty'
|
||||
assert move.weight == 0.5, 'wrong move weight'
|
||||
assert move.weight_net == 0.4, 'wrong move weight_net'
|
||||
-
|
||||
ship
|
||||
-
|
||||
!python {model: sale.order, id: sale_prepaid}: |
|
||||
picking = self.picking_ids.action_done()
|
||||
-
|
||||
Check the SO after shipping
|
||||
-
|
||||
!python {model: sale.order, id: sale_prepaid}: |
|
||||
assert self.state == 'done'
|
||||
@@ -192,12 +192,12 @@ class Proxy(http.Controller):
|
||||
print 'print_receipt' + str(receipt)
|
||||
|
||||
@http.route('/hw_proxy/is_scanner_connected', type='json', auth='none', cors='*')
|
||||
def print_receipt(self, receipt):
|
||||
def is_scanner_connected(self, receipt):
|
||||
print 'is_scanner_connected?'
|
||||
return False
|
||||
|
||||
@http.route('/hw_proxy/scanner', type='json', auth='none', cors='*')
|
||||
def print_receipt(self, receipt):
|
||||
def scanner(self, receipt):
|
||||
print 'scanner'
|
||||
time.sleep(10)
|
||||
return ''
|
||||
|
||||
@@ -37,6 +37,7 @@ such as the Mettler Toledo Ariva.
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'depends': ['hw_proxy'],
|
||||
'external_dependencies': {'python': ['serial']},
|
||||
'test': [
|
||||
],
|
||||
'installable': True,
|
||||
|
||||
@@ -178,28 +178,34 @@ class Scale(Thread):
|
||||
if not self.device:
|
||||
time.sleep(5)
|
||||
|
||||
s = Scale()
|
||||
|
||||
hw_proxy.drivers['scale'] = s
|
||||
scale_thread = None
|
||||
if serial:
|
||||
scale_thread = Scale()
|
||||
hw_proxy.drivers['scale'] = scale_thread
|
||||
|
||||
class ScaleDriver(hw_proxy.Proxy):
|
||||
@http.route('/hw_proxy/scale_read/', type='json', auth='none', cors='*')
|
||||
def scale_read(self):
|
||||
return {'weight':s.get_weight(), 'unit':'kg', 'info':s.get_weight_info()}
|
||||
if scale_thread:
|
||||
return {'weight': scale_thread.get_weight(), 'unit':'kg', 'info': scale_thread.get_weight_info()}
|
||||
return None
|
||||
|
||||
@http.route('/hw_proxy/scale_zero/', type='json', auth='none', cors='*')
|
||||
def scale_zero(self):
|
||||
s.set_zero()
|
||||
if scale_thread:
|
||||
scale_thread.set_zero()
|
||||
return True
|
||||
|
||||
@http.route('/hw_proxy/scale_tare/', type='json', auth='none', cors='*')
|
||||
def scale_tare(self):
|
||||
s.set_tare()
|
||||
if scale_thread:
|
||||
scale_thread.set_tare()
|
||||
return True
|
||||
|
||||
@http.route('/hw_proxy/scale_clear_tare/', type='json', auth='none', cors='*')
|
||||
def scale_clear_tare(self):
|
||||
s.clear_tare()
|
||||
if scale_thread:
|
||||
scale_thread.clear_tare()
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ point of sale module.
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'depends': ['hw_proxy'],
|
||||
'external_dependencies': {'python': ['evdev']},
|
||||
'test': [
|
||||
],
|
||||
'installable': True,
|
||||
|
||||
@@ -111,8 +111,6 @@ class Scanner(Thread):
|
||||
|
||||
def get_device(self):
|
||||
try:
|
||||
if not evdev:
|
||||
return None
|
||||
devices = [ device for device in listdir(self.input_dir)]
|
||||
keyboards = [ device for device in devices if ('kbd' in device) and ('keyboard' not in device.lower())]
|
||||
scanners = [ device for device in devices if ('barcode' in device.lower()) or ('scanner' in device.lower())]
|
||||
@@ -135,7 +133,6 @@ class Scanner(Thread):
|
||||
been returned before. This is necessary to catch barcodes scanned while the POS is
|
||||
busy reading another barcode
|
||||
"""
|
||||
|
||||
self.lockedstart()
|
||||
|
||||
while True:
|
||||
@@ -204,12 +201,12 @@ class Scanner(Thread):
|
||||
except Exception as e:
|
||||
self.set_status('error',str(e))
|
||||
|
||||
s = Scanner()
|
||||
|
||||
hw_proxy.drivers['scanner'] = s
|
||||
scanner_thread = None
|
||||
if evdev:
|
||||
scanner_thread = Scanner()
|
||||
hw_proxy.drivers['scanner'] = scanner_thread
|
||||
|
||||
class ScannerDriver(hw_proxy.Proxy):
|
||||
@http.route('/hw_proxy/scanner', type='json', auth='none', cors='*')
|
||||
def scanner(self):
|
||||
return s.get_barcode()
|
||||
|
||||
def scanner_thread(self):
|
||||
return scanner_thread.get_barcode() if scanner_thread else None
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<div class="oe_im">
|
||||
<div class="oe_im_frame_header">
|
||||
<i class="fa fa-search oe_im_search_icon"/>
|
||||
<input class="oe_im_searchbox" t-att-placeholder="_t('Search users...')"/>
|
||||
<input class="oe_im_searchbox" placeholder="Search users..."/>
|
||||
</div>
|
||||
<div class="oe_im_users"></div>
|
||||
<div class="oe_im_content"></div>
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_view_mass_mailing_lists">
|
||||
<field name="name">Contact Lists</field>
|
||||
<field name="name">Mailing Lists</field>
|
||||
<field name="res_model">mail.mass_mailing.list</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
|
||||
+6
-4
@@ -25,7 +25,7 @@ from collections import OrderedDict
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
|
||||
from openerp.tools import float_compare
|
||||
from openerp.tools import float_compare, float_is_zero
|
||||
from openerp.tools.translate import _
|
||||
from openerp import tools, SUPERUSER_ID
|
||||
from openerp.addons.product import _common
|
||||
@@ -604,7 +604,7 @@ class mrp_production(osv.osv):
|
||||
'date_planned': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'product_qty': lambda *a: 1.0,
|
||||
'user_id': lambda self, cr, uid, c: uid,
|
||||
'name': lambda x, y, z, c: x.pool.get('ir.sequence').next_by_code(y, z, 'mrp.production') or '/',
|
||||
'name': lambda self, cr, uid, context: self.pool['ir.sequence'].next_by_code(cr, uid, 'mrp.production', context=context) or '/',
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.production', context=c),
|
||||
'location_src_id': _src_id_default,
|
||||
'location_dest_id': _dest_id_default
|
||||
@@ -949,6 +949,7 @@ class mrp_production(osv.osv):
|
||||
uom_obj = self.pool.get("product.uom")
|
||||
production = self.browse(cr, uid, production_id, context=context)
|
||||
production_qty_uom = uom_obj._compute_qty(cr, uid, production.product_uom.id, production_qty, production.product_id.uom_id.id)
|
||||
precision = self.pool['decimal.precision'].precision_get(cr, uid, 'Product Unit of Measure')
|
||||
|
||||
main_production_move = False
|
||||
if production_mode == 'consume_produce':
|
||||
@@ -970,7 +971,8 @@ class mrp_production(osv.osv):
|
||||
location_id=produce_product.location_id.id, restrict_lot_id=lot_id, context=context)
|
||||
stock_mov_obj.write(cr, uid, new_moves, {'production_id': production_id}, context=context)
|
||||
remaining_qty = subproduct_factor * production_qty_uom - qty
|
||||
if remaining_qty: # In case you need to make more than planned
|
||||
if not float_is_zero(remaining_qty, precision_rounding=precision):
|
||||
# In case you need to make more than planned
|
||||
#consumed more in wizard than previously planned
|
||||
extra_move_id = stock_mov_obj.copy(cr, uid, produce_product.id, default={'product_uom_qty': remaining_qty,
|
||||
'production_id': production_id}, context=context)
|
||||
@@ -1000,7 +1002,7 @@ class mrp_production(osv.osv):
|
||||
stock_mov_obj.action_consume(cr, uid, [raw_material_line.id], consumed_qty, raw_material_line.location_id.id,
|
||||
restrict_lot_id=consume['lot_id'], consumed_for=main_production_move, context=context)
|
||||
remaining_qty -= consumed_qty
|
||||
if remaining_qty:
|
||||
if not float_is_zero(remaining_qty, precision_rounding=precision):
|
||||
#consumed more in wizard than previously planned
|
||||
product = self.pool.get('product.product').browse(cr, uid, consume['product_id'], context=context)
|
||||
extra_move_id = self._make_consume_line_from_data(cr, uid, production, product, product.uom_id.id, remaining_qty, False, 0, context=context)
|
||||
|
||||
@@ -117,7 +117,7 @@ class procurement_order(osv.osv):
|
||||
if self.check_bom_exists(cr, uid, [procurement.id], context=context):
|
||||
#create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example)
|
||||
vals = self._prepare_mo_vals(cr, uid, procurement, context=context)
|
||||
produce_id = production_obj.create(cr, SUPERUSER_ID, vals, context=context)
|
||||
produce_id = production_obj.create(cr, SUPERUSER_ID, vals, context=dict(context, force_company=procurement.company_id.id))
|
||||
res[procurement.id] = produce_id
|
||||
self.write(cr, uid, [procurement.id], {'production_id': produce_id})
|
||||
self.production_order_create_note(cr, uid, procurement, context=context)
|
||||
|
||||
@@ -28,7 +28,7 @@ class AcquirerAdyen(osv.Model):
|
||||
- yhpp: hosted payment page: pay.shtml for single, select.shtml for multiple
|
||||
"""
|
||||
return {
|
||||
'adyen_form_url': 'https://%s.adyen.com/hpp/pay.shtml' % environment,
|
||||
'adyen_form_url': 'https://%s.adyen.com/hpp/pay.shtml' % 'live' if environment == 'prod' else environment,
|
||||
}
|
||||
|
||||
def _get_providers(self, cr, uid, context=None):
|
||||
|
||||
@@ -129,13 +129,7 @@ class pos_details(report_sxw.rml_parse):
|
||||
return {}
|
||||
|
||||
def _total_of_the_day(self, objects):
|
||||
if self.total:
|
||||
if self.total == self.total_invoiced:
|
||||
return self.total
|
||||
else:
|
||||
return ((self.total or 0.00) - (self.total_invoiced or 0.00))
|
||||
else:
|
||||
return False
|
||||
return self.total or 0.00
|
||||
|
||||
def _sum_invoice(self, objects):
|
||||
return reduce(lambda acc, obj:
|
||||
|
||||
@@ -170,7 +170,7 @@ openerp.point_of_sale.load_db = function load_db(instance, module){
|
||||
for (var i = 0; i < packagings.length; i++) {
|
||||
str += '|' + packagings[i].barcode;
|
||||
}
|
||||
str = product.id + ':' + str.replace(':','') + '\n';
|
||||
str = product.id + ':' + str.replace(/:/g,'') + '\n';
|
||||
return str;
|
||||
},
|
||||
add_products: function(products){
|
||||
|
||||
@@ -1196,18 +1196,19 @@ class procurement_order(osv.osv):
|
||||
uom_obj = self.pool.get("product.uom")
|
||||
for procurement in self.browse(cr, uid, ids, context=context):
|
||||
if procurement.rule_id.action == 'buy' and procurement.purchase_line_id:
|
||||
uom = procurement.purchase_line_id.product_uom
|
||||
product_qty = uom_obj._compute_qty_obj(cr, uid, procurement.product_uom, procurement.product_qty, uom, context=context)
|
||||
if procurement.purchase_line_id.state not in ('draft', 'cancel'):
|
||||
raise UserError(
|
||||
_('Can not cancel this procurement like this as the related purchase order has been confirmed already. Please cancel the purchase order first. '))
|
||||
if float_compare(procurement.purchase_line_id.product_qty, product_qty, 0, precision_rounding=uom.rounding) > 0:
|
||||
purchase_line_obj.write(cr, uid, [procurement.purchase_line_id.id], {'product_qty': procurement.purchase_line_id.product_qty - product_qty}, context=context)
|
||||
else:
|
||||
|
||||
new_qty, new_price = self._calc_new_qty_price(cr, uid, procurement, cancel=True, context=context)
|
||||
if new_qty != procurement.purchase_line_id.product_qty:
|
||||
purchase_line_obj.write(cr, uid, [procurement.purchase_line_id.id], {'product_qty': new_qty, 'price_unit': new_price}, context=context)
|
||||
if float_compare(new_qty, 0.0, precision_rounding=procurement.product_uom.rounding) != 1:
|
||||
if procurement.purchase_line_id.id not in lines_to_cancel:
|
||||
lines_to_cancel += [procurement.purchase_line_id.id]
|
||||
if lines_to_cancel:
|
||||
purchase_line_obj.action_cancel(cr, uid, lines_to_cancel, context=context)
|
||||
purchase_line_obj.unlink(cr, uid, lines_to_cancel, context=context)
|
||||
return super(procurement_order, self).propagate_cancels(cr, uid, ids, context=context)
|
||||
|
||||
def _run(self, cr, uid, procurement, context=None):
|
||||
@@ -1371,6 +1372,41 @@ class procurement_order(osv.osv):
|
||||
res[procurement.id] = values
|
||||
return res
|
||||
|
||||
def _calc_new_qty_price(self, cr, uid, procurement, po_line=None, cancel=False, context=None):
|
||||
if not po_line:
|
||||
po_line = procurement.purchase_line_id
|
||||
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty,
|
||||
procurement.product_id.uom_po_id.id)
|
||||
if cancel:
|
||||
qty = -qty
|
||||
|
||||
# Make sure we use the minimum quantity of the partner corresponding to the PO
|
||||
if po_line.product_id.seller_id.id == po_line.order_id.partner_id.id:
|
||||
supplierinfo_min_qty = po_line.product_id.seller_qty
|
||||
else:
|
||||
supplierinfo_obj = self.pool.get('product.supplierinfo')
|
||||
supplierinfo_ids = supplierinfo_obj.search(cr, uid, [('name', '=', po_line.order_id.partner_id.id), ('product_tmpl_id', '=', po_line.product_id.product_tmpl_id.id)])
|
||||
supplierinfo_min_qty = supplierinfo_obj.browse(cr, uid, supplierinfo_ids).min_qty
|
||||
|
||||
if supplierinfo_min_qty == 0.0:
|
||||
qty += po_line.product_qty
|
||||
else:
|
||||
# Recompute quantity by adding existing running procurements.
|
||||
for proc in po_line.procurement_ids:
|
||||
qty += uom_obj._compute_qty(cr, uid, proc.product_uom.id, proc.product_qty,
|
||||
proc.product_id.uom_po_id.id) if proc.state == 'running' else 0.0
|
||||
qty = max(qty, supplierinfo_min_qty) if qty > 0.0 else 0.0
|
||||
|
||||
price = po_line.price_unit
|
||||
if qty != po_line.product_qty:
|
||||
pricelist_obj = self.pool.get('product.pricelist')
|
||||
pricelist_id = po_line.order_id.partner_id.property_product_pricelist_purchase.id
|
||||
price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, po_line.order_id.partner_id.id, {'uom': procurement.product_uom.id})[pricelist_id]
|
||||
|
||||
return qty, price
|
||||
|
||||
def _get_grouping_dicts(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
It will group the procurements according to the pos they should go into. That way, lines going to the same
|
||||
@@ -1455,8 +1491,11 @@ class procurement_order(osv.osv):
|
||||
for proc in procurements:
|
||||
if po_prod_dict.get(proc.product_id.id):
|
||||
po_line = po_prod_dict[proc.product_id.id]
|
||||
uom_id = po_line.product_uom #Convert to UoM of existing line
|
||||
# FIXME: compute quantity using `_calc_new_qty_price` method.
|
||||
# new_qty, new_price = self._calc_new_qty_price(cr, uid, proc, po_line=po_line, context=context)
|
||||
uom_id = po_line.product_uom # Convert to UoM of existing line
|
||||
qty = uom_obj._compute_qty_obj(cr, uid, proc.product_uom, proc.product_qty, uom_id)
|
||||
|
||||
if lines_to_update.get(po_line):
|
||||
lines_to_update[po_line] += [(proc.id, qty)]
|
||||
else:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
-
|
||||
!python {model: sale.order}: |
|
||||
sale_order = self.browse(cr, uid, ref("sale_order_2"))
|
||||
assert len(sale_order.invoice_ids) == False, "Invoice should not created."
|
||||
assert len(sale_order.invoice_ids) == 0, "Invoice should not created."
|
||||
-
|
||||
I create advance invoice where type is 'Fixed Price'.
|
||||
-
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
report_layout_category_1,report_layout_category_1,model_sale_layout_category,base.group_sale_manager,1,1,1,1
|
||||
report_layout_category_2,report_layout_category_2,model_sale_layout_category,account.group_account_manager,1,1,1,1
|
||||
report_layout_category_3,report_layout_category_3,model_sale_layout_category,base.group_sale_salesman,1,1,1,O
|
||||
report_layout_category_3,report_layout_category_3,model_sale_layout_category,base.group_sale_salesman,1,1,1,0
|
||||
report_layout_category_4,report_layout_category_4,model_sale_layout_category,base.group_sale_salesman_all_leads,1,1,1,0
|
||||
report_layout_category_5,report_layout_category_5,model_sale_layout_category,account.group_account_invoice,1,0,0,0
|
||||
|
||||
|
+43
-8
@@ -1627,7 +1627,7 @@ class stock_production_lot(osv.osv):
|
||||
# Move
|
||||
# ----------------------------------------------------
|
||||
|
||||
class stock_move(models.Model):
|
||||
class stock_move(osv.osv):
|
||||
_name = "stock.move"
|
||||
_description = "Stock Move"
|
||||
_order = 'picking_id, sequence, id'
|
||||
@@ -1648,11 +1648,12 @@ class stock_move(models.Model):
|
||||
res.append((line.id, name))
|
||||
return res
|
||||
|
||||
@api.depends('product_id', 'product_uom_qty', 'product_uom', 'product_id.uom_id')
|
||||
def _quantity_normalize(self):
|
||||
def _quantity_normalize(self, cr, uid, ids, name, args, context=None):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
for m in self:
|
||||
m.product_qty = uom_obj._compute_qty_obj(self.env.cr, self.env.uid, m.product_uom, m.product_uom_qty, m.product_id.uom_id, context=self.env.context)
|
||||
res = {}
|
||||
for m in self.browse(cr, uid, ids, context=context):
|
||||
res[m.id] = uom_obj._compute_qty_obj(cr, uid, m.product_uom, m.product_uom_qty, m.product_id.uom_id, context=context)
|
||||
return res
|
||||
|
||||
def _get_remaining_qty(self, cr, uid, ids, field_name, args, context=None):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
@@ -1736,6 +1737,11 @@ class stock_move(models.Model):
|
||||
res += [x.id for x in picking.move_lines]
|
||||
return res
|
||||
|
||||
def _get_moves_from_prod(self, cr, uid, ids, context=None):
|
||||
if ids:
|
||||
return self.pool.get('stock.move').search(cr, uid, [('product_id', 'in', ids)], context=context)
|
||||
return []
|
||||
|
||||
def _set_product_qty(self, cr, uid, id, field, value, arg, context=None):
|
||||
""" The meaning of product_qty field changed lately and is now a functional field computing the quantity
|
||||
in the default product UoM. This code has been added to raise an error if a write is made given a value
|
||||
@@ -1744,9 +1750,6 @@ class stock_move(models.Model):
|
||||
"""
|
||||
raise UserError(_('The requested operation cannot be processed because of a programming error setting the `product_qty` field instead of the `product_uom_qty`.'))
|
||||
|
||||
product_qty = new_fields.Float(compute='_quantity_normalize', inverse='_set_product_qty', digits=0, store=True, string='Quantity',
|
||||
help='Quantity in the default UoM of the product')
|
||||
|
||||
_columns = {
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'name': fields.char('Description', required=True, select=True),
|
||||
@@ -1755,6 +1758,8 @@ class stock_move(models.Model):
|
||||
'date': fields.datetime('Date', required=True, select=True, help="Move date: scheduled date until move is done, then date of actual move processing", states={'done': [('readonly', True)]}),
|
||||
'date_expected': fields.datetime('Expected Date', states={'done': [('readonly', True)]}, required=True, select=True, help="Scheduled date for the processing of this move"),
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True, select=True, domain=[('type', '<>', 'service')], states={'done': [('readonly', True)]}),
|
||||
'product_qty': fields.function(_quantity_normalize, fnct_inv=_set_product_qty, type='float', digits=0, store=True, string='Quantity',
|
||||
help='Quantity in the default UoM of the product'),
|
||||
'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
required=True, states={'done': [('readonly', True)]},
|
||||
help="This is the quantity of products from an inventory "
|
||||
@@ -2759,6 +2764,36 @@ class stock_inventory(osv.osv):
|
||||
vals.append(product_line)
|
||||
return vals
|
||||
|
||||
def _check_filter_product(self, cr, uid, ids, context=None):
|
||||
for inventory in self.browse(cr, uid, ids, context=context):
|
||||
if inventory.filter == 'none' and inventory.product_id and inventory.location_id and inventory.lot_id:
|
||||
return True
|
||||
if inventory.filter not in ('product', 'product_owner') and inventory.product_id:
|
||||
return False
|
||||
if inventory.filter != 'lot' and inventory.lot_id:
|
||||
return False
|
||||
if inventory.filter not in ('owner', 'product_owner') and inventory.partner_id:
|
||||
return False
|
||||
if inventory.filter != 'pack' and inventory.package_id:
|
||||
return False
|
||||
return True
|
||||
|
||||
def onchange_filter(self, cr, uid, ids, filter, context=None):
|
||||
to_clean = { 'value': {} }
|
||||
if filter not in ('product', 'product_owner'):
|
||||
to_clean['value']['product_id'] = False
|
||||
if filter != 'lot':
|
||||
to_clean['value']['lot_id'] = False
|
||||
if filter not in ('owner', 'product_owner'):
|
||||
to_clean['value']['partner_id'] = False
|
||||
if filter != 'pack':
|
||||
to_clean['value']['package_id'] = False
|
||||
return to_clean
|
||||
|
||||
_constraints = [
|
||||
(_check_filter_product, 'The selected inventory options are not coherent.',
|
||||
['filter', 'product_id', 'lot_id', 'partner_id', 'package_id']),
|
||||
]
|
||||
|
||||
class stock_inventory_line(osv.osv):
|
||||
_name = "stock.inventory.line"
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
<group>
|
||||
<group>
|
||||
<field name="location_id" domain="[('usage','not in', ['supplier','production'])]"/>
|
||||
<field name="filter" string="Inventory of" widget='radio' attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
||||
<field name="filter" string="Inventory of" widget='radio' attrs="{'readonly': [('state', '!=', 'draft')]}" on_change="onchange_filter(filter)"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date"/>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
-
|
||||
!record {model: stock.inventory, id: inventory_test0}:
|
||||
name: Test
|
||||
filter: product
|
||||
product_id: inventory_product
|
||||
-
|
||||
I confirm the inventory and check that my inventory has no line, as the product is a new one.
|
||||
@@ -60,6 +61,7 @@
|
||||
-
|
||||
!record {model: stock.inventory, id: inventory_test1}:
|
||||
name: second test inventory
|
||||
filter: product
|
||||
product_id: inventory_product
|
||||
-
|
||||
I confirm the inventory and check that my inventory has one line, with a quantity of 10.
|
||||
|
||||
@@ -94,8 +94,15 @@ class stock_change_product_qty(osv.osv_memory):
|
||||
ctx = context.copy()
|
||||
ctx['location'] = data.location_id.id
|
||||
ctx['lot_id'] = data.lot_id.id
|
||||
if data.product_id.id and data.lot_id.id:
|
||||
filter = 'none'
|
||||
elif data.product_id.id:
|
||||
filter = 'product'
|
||||
else:
|
||||
filter = 'none'
|
||||
inventory_id = inventory_obj.create(cr, uid, {
|
||||
'name': _('INV: %s') % tools.ustr(data.product_id.name),
|
||||
'filter': filter,
|
||||
'product_id': data.product_id.id,
|
||||
'location_id': data.location_id.id,
|
||||
'lot_id': data.lot_id.id}, context=context)
|
||||
|
||||
@@ -151,6 +151,13 @@ class stock_move(osv.osv):
|
||||
if move.product_uos:
|
||||
uos_id = move.product_uos.id
|
||||
quantity = move.product_uos_qty
|
||||
|
||||
taxes_ids = []
|
||||
if move.origin_returned_move_id.purchase_line_id.taxes_id:
|
||||
taxes_ids = [tax.id for tax in move.origin_returned_move_id.purchase_line_id.taxes_id]
|
||||
elif move.procurement_id.sale_line_id.tax_id:
|
||||
taxes_ids = [tax.id for tax in move.procurement_id.sale_line_id.tax_id]
|
||||
|
||||
return {
|
||||
'name': move.name,
|
||||
'account_id': account_id,
|
||||
@@ -158,6 +165,7 @@ class stock_move(osv.osv):
|
||||
'uos_id': uos_id,
|
||||
'quantity': quantity,
|
||||
'price_unit': self._get_price_unit_invoice(cr, uid, move, inv_type),
|
||||
'invoice_line_tax_id': [(6, 0, taxes_ids)],
|
||||
'discount': 0.0,
|
||||
'account_analytic_id': False,
|
||||
}
|
||||
@@ -292,6 +300,7 @@ class stock_picking(osv.osv):
|
||||
move_obj = self.pool.get('stock.move')
|
||||
invoices = {}
|
||||
is_extra_move, extra_move_tax = move_obj._get_moves_taxes(cr, uid, moves, context=context)
|
||||
product_price_unit = {}
|
||||
for move in moves:
|
||||
company = move.company_id
|
||||
origin = move.picking_id.name
|
||||
@@ -317,6 +326,10 @@ class stock_picking(osv.osv):
|
||||
invoice_line_vals = move_obj._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context)
|
||||
invoice_line_vals['invoice_id'] = invoices[key]
|
||||
invoice_line_vals['origin'] = origin
|
||||
if not is_extra_move[move.id]:
|
||||
product_price_unit[invoice_line_vals['product_id']] = invoice_line_vals['price_unit']
|
||||
if is_extra_move[move.id] and invoice_line_vals['product_id'] in product_price_unit:
|
||||
invoice_line_vals['price_unit'] = product_price_unit[invoice_line_vals['product_id']]
|
||||
if is_extra_move[move.id] and extra_move_tax[move.picking_id, move.product_id]:
|
||||
invoice_line_vals['invoice_line_tax_id'] = extra_move_tax[move.picking_id, move.product_id]
|
||||
|
||||
|
||||
@@ -6,16 +6,17 @@ from openerp import models, api
|
||||
class sale_order_line(models.Model):
|
||||
_inherit = 'sale.order.line'
|
||||
|
||||
@api.one
|
||||
@api.multi
|
||||
def _check_routing(self, product, warehouse):
|
||||
""" skip stock verification if the route goes from supplier to customer
|
||||
As the product never goes in stock, no need to verify it's availibility
|
||||
"""
|
||||
res = super(sale_order_line, self)._check_routing(product, warehouse)
|
||||
if not res:
|
||||
for pull_rule in self.route_id.pull_ids:
|
||||
if (pull_rule.picking_type_id.default_location_src_id.usage == 'supplier' and
|
||||
pull_rule.picking_type_id.default_location_dest_id.usage == 'customer'):
|
||||
res = True
|
||||
break
|
||||
for line in self:
|
||||
for pull_rule in line.route_id.pull_ids:
|
||||
if (pull_rule.picking_type_id.default_location_src_id.usage == 'supplier' and
|
||||
pull_rule.picking_type_id.default_location_dest_id.usage == 'customer'):
|
||||
res = True
|
||||
break
|
||||
return res
|
||||
|
||||
@@ -1,42 +1,58 @@
|
||||
-
|
||||
Create new product without any routes
|
||||
-
|
||||
!record {model: product.product, id: cross_shop_product}:
|
||||
name: PCE
|
||||
type: product
|
||||
categ_id: product.product_category_1
|
||||
list_price: 100.0
|
||||
standard_price: 70.0
|
||||
seller_ids:
|
||||
- delay: 1
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 5.0
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
-
|
||||
Create a sales order with a line of 100 PCE incoming shipment, with route_id crossdock shipping.
|
||||
-
|
||||
!record {model: sale.order, id: sale_order_crossdock_shpng}:
|
||||
partner_id: base.res_partner_4
|
||||
note: Create Sales order
|
||||
order_line:
|
||||
- product_id: cross_shop_product
|
||||
product_uom_qty: 100.00
|
||||
-
|
||||
Create a supplier.
|
||||
-
|
||||
!record {model: res.partner, id: supplier_crossdock}:
|
||||
name: Crossdocking supplier
|
||||
-
|
||||
Use the warehouse created in cancellation_propagated.yml.
|
||||
-
|
||||
!python {model: stock.warehouse, id: wh_pps}: |
|
||||
assert self.crossdock_route_id.active, 'Crossdock route is not active'
|
||||
-
|
||||
Create new product without any routes.
|
||||
-
|
||||
!record {model: product.product, id: cross_shop_product}:
|
||||
name: PCE
|
||||
type: product
|
||||
categ_id: product.product_category_1
|
||||
list_price: 100.0
|
||||
standard_price: 70.0
|
||||
seller_ids:
|
||||
- delay: 1
|
||||
name: supplier_crossdock
|
||||
min_qty: 2.0
|
||||
qty: 5.0
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
-
|
||||
Create a sales order with a line of 100 PCE incoming shipment, with route_id crossdock shipping.
|
||||
-
|
||||
!record {model: sale.order, id: sale_order_crossdock_shpng}:
|
||||
partner_id: base.res_partner_4
|
||||
warehouse_id: wh_pps
|
||||
note: Create Sales order
|
||||
order_line:
|
||||
- product_id: cross_shop_product
|
||||
product_uom_qty: 100.00
|
||||
-
|
||||
!python {model: sale.order.line}: |
|
||||
route_warehouse0_crossdock = self.pool.get('stock.warehouse').browse(cr, uid, ref('stock.warehouse0')).crossdock_route_id.id
|
||||
route_wh_pps_crossdock = self.pool.get('stock.warehouse').browse(cr, uid, ref('stock_dropshipping.wh_pps')).crossdock_route_id.id
|
||||
order = self.pool.get('sale.order').browse(cr, uid, ref('sale_order_crossdock_shpng'))
|
||||
line_ids = [x.id for x in order.order_line]
|
||||
self.write(cr, uid, line_ids, {'route_id': route_warehouse0_crossdock})
|
||||
-
|
||||
Confirm sales order
|
||||
-
|
||||
!workflow {model: sale.order, action: order_confirm, ref: sale_order_crossdock_shpng}
|
||||
-
|
||||
Check a quotation was created to a certain supplier and confirm so it becomes a confirmed purchase order
|
||||
self.write(cr, uid, line_ids, {'route_id': route_wh_pps_crossdock})
|
||||
-
|
||||
Confirm sales order.
|
||||
-
|
||||
!workflow {model: sale.order, action: order_confirm, ref: sale_order_crossdock_shpng}
|
||||
-
|
||||
Run the scheduler.
|
||||
-
|
||||
!python {model: procurement.order}: |
|
||||
self.run_scheduler(cr, uid)
|
||||
-
|
||||
Check a quotation was created for the created supplier and confirm it.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
po_id = self.search(cr, uid, [('partner_id', '=', ref('base.res_partner_2'))])
|
||||
po_id = self.search(cr, uid, [('partner_id', '=', ref('supplier_crossdock')), ('state','=','draft')])
|
||||
self.wkf_confirm_order(cr, uid, po_id)
|
||||
|
||||
@@ -451,7 +451,7 @@ def content_disposition(filename):
|
||||
if browser == 'msie' and version < 9:
|
||||
return "attachment; filename=%s" % escaped
|
||||
elif browser == 'safari':
|
||||
return "attachment; filename=%s" % filename
|
||||
return "attachment; filename=\"%s\"" % filename
|
||||
else:
|
||||
return "attachment; filename*=UTF-8''%s" % escaped
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
import controllers
|
||||
import models
|
||||
|
||||
@@ -27,7 +27,7 @@ class WebsiteMembership(http.Controller):
|
||||
'/members/association/<membership_id>/country/<country_name>-<int:country_id>/page/<int:page>',
|
||||
'/members/association/<membership_id>/country/<int:country_id>/page/<int:page>',
|
||||
], type='http', auth="public", website=True)
|
||||
def members(self, membership_id=None, country_name=None, country_id=0, page=0, **post):
|
||||
def members(self, membership_id=None, country_name=None, country_id=0, page=1, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
product_obj = request.registry['product.product']
|
||||
country_obj = request.registry['res.country']
|
||||
@@ -56,7 +56,7 @@ class WebsiteMembership(http.Controller):
|
||||
membership_line_ids = []
|
||||
country_domain = ('free_member', '=', True)
|
||||
countries = partner_obj.read_group(
|
||||
cr, uid, [country_domain, ("website_published", "=", True)], ["id", "country_id"],
|
||||
cr, SUPERUSER_ID, [country_domain, ("website_published", "=", True)], ["id", "country_id"],
|
||||
groupby="country_id", orderby="country_id", context=request.context)
|
||||
countries_total = sum(country_dict['country_id_count'] for country_dict in countries)
|
||||
|
||||
@@ -64,11 +64,12 @@ class WebsiteMembership(http.Controller):
|
||||
if country_id:
|
||||
line_domain.append(('partner.country_id', '=', country_id))
|
||||
current_country = country_obj.read(cr, uid, country_id, ['id', 'name'], context)
|
||||
if not any(x['country_id'][0] == country_id for x in countries):
|
||||
if not any(x['country_id'][0] == country_id for x in countries if x['country_id']):
|
||||
countries.append({
|
||||
'country_id_count': 0,
|
||||
'country_id': (country_id, current_country["name"])
|
||||
})
|
||||
countries = filter(lambda d:d['country_id'], countries)
|
||||
countries.sort(key=lambda d: d['country_id'][1])
|
||||
|
||||
countries.insert(0, {
|
||||
@@ -82,15 +83,32 @@ class WebsiteMembership(http.Controller):
|
||||
# make sure we don't access to lines with unpublished membershipts
|
||||
line_domain.append(('membership_id', 'in', membership_ids))
|
||||
|
||||
# displayed membership lines
|
||||
limit = self._references_per_page
|
||||
offset = limit * (page - 1)
|
||||
|
||||
count_members = 0
|
||||
membership_line_ids = []
|
||||
# displayed non-free membership lines
|
||||
if membership_id != 'free':
|
||||
membership_line_ids = membership_line_obj.search(cr, SUPERUSER_ID, line_domain, context=context)
|
||||
count_members = membership_line_obj.search_count(cr, SUPERUSER_ID, line_domain, context=context)
|
||||
if offset <= count_members:
|
||||
membership_line_ids = tuple(membership_line_obj.search(cr, SUPERUSER_ID, line_domain, offset, limit, context=context))
|
||||
membership_lines = membership_line_obj.browse(cr, uid, membership_line_ids, context=context)
|
||||
# TODO: Following line can be deleted in master. Kept for retrocompatibility.
|
||||
membership_lines = sorted(membership_lines, key=lambda x: x.membership_id.website_sequence)
|
||||
partner_ids = [m.partner.id for m in membership_lines]
|
||||
free_partner_ids = partner_obj.search(cr, SUPERUSER_ID, [('free_member', '=', True), ('website_published', '=', True)], context=context)
|
||||
google_map_partner_ids = ",".join(map(str, partner_ids))
|
||||
page_partner_ids = set(m.partner.id for m in membership_lines)
|
||||
|
||||
google_map_partner_ids = []
|
||||
if request.env.ref('website_membership.opt_index_google_map').customize_show:
|
||||
membership_lines_ids = membership_line_obj.search(cr, uid, line_domain, context=context)
|
||||
google_map_partner_ids = membership_line_obj.get_published_companies(cr, uid, membership_line_ids, limit=2000, context=context)
|
||||
|
||||
search_domain = [('free_member', '=', True), ('website_published', '=', True)]
|
||||
if post_name:
|
||||
search_domain += ['|', ('name', 'ilike', post_name), ('website_description', 'ilike', post_name)]
|
||||
if country_id:
|
||||
search_domain += [('country_id', '=', country_id)]
|
||||
free_partner_ids = partner_obj.search(cr, SUPERUSER_ID, search_domain, context=context)
|
||||
memberships_data = []
|
||||
for membership_record in memberships:
|
||||
memberships_data.append({'id': membership_record.id, 'name': membership_record.name})
|
||||
@@ -100,12 +118,23 @@ class WebsiteMembership(http.Controller):
|
||||
if free_partner_ids:
|
||||
memberships_data.append({'id': 'free', 'name': _('Free Members')})
|
||||
if not membership_id or membership_id == 'free':
|
||||
memberships_partner_ids['free'] = free_partner_ids
|
||||
if count_members < offset + limit:
|
||||
free_start = max(offset - count_members, 0)
|
||||
free_end = max(offset + limit - count_members, 0)
|
||||
memberships_partner_ids['free'] = free_partner_ids[free_start:free_end]
|
||||
page_partner_ids |= set(memberships_partner_ids['free'])
|
||||
google_map_partner_ids += free_partner_ids[:2000-len(google_map_partner_ids)]
|
||||
count_members += len(free_partner_ids)
|
||||
|
||||
partners = dict((p.id, p) for p in partner_obj.browse(request.cr, SUPERUSER_ID, list(set(partner_ids + free_partner_ids)), request.context))
|
||||
google_map_partner_ids = ",".join(map(str, google_map_partner_ids))
|
||||
|
||||
partners = { p.id: p for p in partner_obj.browse(request.cr, SUPERUSER_ID, list(page_partner_ids), request.context)}
|
||||
|
||||
base_url = '/members%s%s' % ('/association/%s' % membership_id if membership_id else '',
|
||||
'/country/%s' % country_id if country_id else '')
|
||||
|
||||
# request pager for lines
|
||||
pager = request.website.pager(url="/members", total=len(membership_line_ids), page=page, step=self._references_per_page, scope=7, url_args=post)
|
||||
pager = request.website.pager(url=base_url, total=count_members, page=page, step=limit, scope=7, url_args=post)
|
||||
|
||||
values = {
|
||||
'partners': partners,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import membership
|
||||
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
class membership_membership_line(osv.Model):
|
||||
_inherit = 'membership.membership_line'
|
||||
|
||||
def get_published_companies(self, cr, uid, ids, limit=None, context=None):
|
||||
if not ids:
|
||||
return []
|
||||
limit_clause = '' if limit is None else ' LIMIT %d' % limit
|
||||
cr.execute('SELECT DISTINCT p.id \
|
||||
FROM res_partner p INNER JOIN membership_membership_line m \
|
||||
ON p.id = m.partner \
|
||||
WHERE website_published AND is_company AND m.id IN %s ' + limit_clause, (tuple(ids),))
|
||||
return [partner_id[0] for partner_id in cr.fetchall()]
|
||||
@@ -279,6 +279,8 @@ class sale_quote_option(osv.osv):
|
||||
'name': product_obj.name,
|
||||
'uom_id': product_obj.product_tmpl_id.uom_id.id,
|
||||
})
|
||||
if product_obj.description_sale:
|
||||
vals['name'] += '\n'+product_obj.description_sale
|
||||
return {'value': vals}
|
||||
|
||||
class sale_order_option(osv.osv):
|
||||
@@ -311,6 +313,8 @@ class sale_order_option(osv.osv):
|
||||
'name': product_obj.name,
|
||||
'uom_id': product_obj.product_tmpl_id.uom_id.id,
|
||||
})
|
||||
if product_obj.description_sale:
|
||||
vals['name'] += '\n'+product_obj.description_sale
|
||||
return {'value': vals}
|
||||
|
||||
class product_template(osv.Model):
|
||||
|
||||
@@ -42,6 +42,11 @@
|
||||
padding-left: 30px;
|
||||
font-size: 90%;
|
||||
}
|
||||
@media (max-width: 991px) {
|
||||
.o_website_quote .bs-sidebar {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.o_website_quote .bs-sidebar .nav > .active > ul {
|
||||
display: block;
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
|
||||
<template id="quotation_toolbar">
|
||||
<div class="text-center hidden-print" t-if="quotation.state in ('draft', 'sent', 'waiting_date')">
|
||||
<a class="btn btn-success" data-toggle="modal" data-target="#modalaccept"
|
||||
<a class="btn btn-success" data-toggle="modal" data-target="#modelaccept"
|
||||
t-if="days_valid >= 0">
|
||||
<i class="fa fa-check"></i> Accept
|
||||
</a>
|
||||
|
||||
@@ -980,10 +980,13 @@ class website_sale(http.Controller):
|
||||
return ret
|
||||
|
||||
@http.route(['/shop/get_unit_price'], type='json', auth="public", methods=['POST'], website=True)
|
||||
def get_unit_price(self, product_ids, add_qty, **kw):
|
||||
def get_unit_price(self, product_ids, add_qty, use_order_pricelist=False, **kw):
|
||||
cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
|
||||
products = pool['product.product'].browse(cr, uid, product_ids, context=context)
|
||||
partner = pool['res.users'].browse(cr, uid, uid, context=context).partner_id
|
||||
pricelist_id = request.session.get('sale_order_code_pricelist_id') or partner.property_product_pricelist.id
|
||||
if use_order_pricelist:
|
||||
pricelist_id = request.session.get('sale_order_code_pricelist_id') or partner.property_product_pricelist.id
|
||||
else:
|
||||
pricelist_id = partner.property_product_pricelist.id
|
||||
prices = pool['product.pricelist'].price_rule_get_multi(cr, uid, [], [(product, add_qty, partner) for product in products], context=context)
|
||||
return {product_id: prices[product_id][pricelist_id][0] for product_id in product_ids}
|
||||
|
||||
@@ -56,7 +56,8 @@ $('.oe_website_sale').each(function () {
|
||||
if (isNaN(value)) value = 0;
|
||||
openerp.jsonRpc("/shop/get_unit_price", 'call', {
|
||||
'product_ids': product_ids,
|
||||
'add_qty': value})
|
||||
'add_qty': value,
|
||||
'use_order_pricelist': true})
|
||||
.then(function (res) {
|
||||
//basic case
|
||||
$dom.find('span.oe_currency_value').last().text(res[product_id].toFixed(2));
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
China, 2015-04-25
|
||||
|
||||
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,
|
||||
|
||||
Jeffery Chen Fan jeffery9@gmail.com https://github.com/jeffery9
|
||||
@@ -0,0 +1,11 @@
|
||||
La Habana, 2015-04-30
|
||||
|
||||
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,
|
||||
|
||||
Manuel Vázquez Acosta mva.led@gmail.com https://github.com/mvaled
|
||||
@@ -0,0 +1,11 @@
|
||||
Brazil, 2015-04-28
|
||||
|
||||
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,
|
||||
|
||||
Rui Andrada shingonoide@gmail.com https://github.com/shingonoide
|
||||
@@ -764,6 +764,7 @@ method should simply set the value of the field to compute on every record in
|
||||
|
||||
name = fields.Char(compute='_compute_name')
|
||||
|
||||
@api.multi
|
||||
def _compute_name(self):
|
||||
for record in self:
|
||||
record.name = str(random.randint(1, 1e6))
|
||||
|
||||
@@ -35,7 +35,7 @@ Index: addons/openacademy/views/openacademy.xml
|
||||
===================================================================
|
||||
--- addons.orig/openacademy/views/openacademy.xml 2014-08-28 14:21:46.543015785 +0200
|
||||
+++ addons/openacademy/views/openacademy.xml 2014-08-28 14:21:46.539015785 +0200
|
||||
@@ -145,11 +145,24 @@
|
||||
@@ -145,11 +145,23 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -44,10 +44,9 @@ Index: addons/openacademy/views/openacademy.xml
|
||||
+ <field name="model">openacademy.session</field>
|
||||
+ <field name="arch" type="xml">
|
||||
+ <gantt string="Session Gantt" color="course_id"
|
||||
+ date_start="start_date" date_delay="hours">
|
||||
+ <level object="res.partner" link="instructor_id">
|
||||
+ <field name="name"/>
|
||||
+ </level>
|
||||
+ date_start="start_date" date_delay="hours"
|
||||
+ default_group_by='instructor_id'>
|
||||
+ <field name="name"/>
|
||||
+ </gantt>
|
||||
+ </field>
|
||||
+ </record>
|
||||
|
||||
@@ -5,7 +5,7 @@ Index: addons/openacademy/views/session_workflow.xml
|
||||
===================================================================
|
||||
--- addons.orig/openacademy/views/session_workflow.xml 2014-08-26 17:26:17.339783114 +0200
|
||||
+++ addons/openacademy/views/session_workflow.xml 2014-08-26 17:26:17.331783114 +0200
|
||||
@@ -6,24 +6,53 @@
|
||||
@@ -6,24 +6,50 @@
|
||||
<field name="on_create">True</field>
|
||||
</record>
|
||||
|
||||
@@ -13,8 +13,7 @@ Index: addons/openacademy/views/session_workflow.xml
|
||||
+ <field name="name">Set session to Draft</field>
|
||||
+ <field name="model_id" ref="model_openacademy_session"/>
|
||||
+ <field name="code">
|
||||
+recs = self.browse(cr, uid, context['active_ids'], context=context)
|
||||
+recs.action_draft()
|
||||
+model.search([('id', 'in', context['active_ids'])]).action_draft()
|
||||
+ </field>
|
||||
+ </record>
|
||||
<record model="workflow.activity" id="draft">
|
||||
@@ -32,8 +31,7 @@ Index: addons/openacademy/views/session_workflow.xml
|
||||
+ <field name="name">Set session to Confirmed</field>
|
||||
+ <field name="model_id" ref="model_openacademy_session"/>
|
||||
+ <field name="code">
|
||||
+recs = self.browse(cr, uid, context['active_ids'], context=context)
|
||||
+recs.action_confirm()
|
||||
+model.search([('id', 'in', context['active_ids'])]).action_confirm()
|
||||
+ </field>
|
||||
</record>
|
||||
<record model="workflow.activity" id="confirmed">
|
||||
@@ -50,8 +48,7 @@ Index: addons/openacademy/views/session_workflow.xml
|
||||
+ <field name="name">Set session to Done</field>
|
||||
+ <field name="model_id" ref="model_openacademy_session"/>
|
||||
+ <field name="code">
|
||||
+recs = self.browse(cr, uid, context['active_ids'], context=context)
|
||||
+recs.action_done()
|
||||
+model.search([('id', 'in', context['active_ids'])]).action_done()
|
||||
+ </field>
|
||||
</record>
|
||||
<record model="workflow.activity" id="done">
|
||||
|
||||
@@ -1046,7 +1046,7 @@ class ir_model_data(osv.osv):
|
||||
|
||||
if action_id and res_id:
|
||||
model_obj.write(cr, uid, [res_id], values, context=context)
|
||||
self.write(cr, uid, [action_id], {
|
||||
self.write(cr, SUPERUSER_ID, [action_id], {
|
||||
'date_update': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
},context=context)
|
||||
elif res_id:
|
||||
@@ -1056,14 +1056,14 @@ class ir_model_data(osv.osv):
|
||||
for table in model_obj._inherits:
|
||||
inherit_id = model_obj.browse(cr, uid,
|
||||
res_id,context=context)[model_obj._inherits[table]]
|
||||
self.create(cr, uid, {
|
||||
self.create(cr, SUPERUSER_ID, {
|
||||
'name': xml_id + '_' + table.replace('.', '_'),
|
||||
'model': table,
|
||||
'module': module,
|
||||
'res_id': inherit_id.id,
|
||||
'noupdate': noupdate,
|
||||
},context=context)
|
||||
self.create(cr, uid, {
|
||||
self.create(cr, SUPERUSER_ID, {
|
||||
'name': xml_id,
|
||||
'model': model,
|
||||
'module':module,
|
||||
@@ -1078,14 +1078,14 @@ class ir_model_data(osv.osv):
|
||||
for table in model_obj._inherits:
|
||||
inherit_id = model_obj.browse(cr, uid,
|
||||
res_id,context=context)[model_obj._inherits[table]]
|
||||
self.create(cr, uid, {
|
||||
self.create(cr, SUPERUSER_ID, {
|
||||
'name': xml_id + '_' + table.replace('.', '_'),
|
||||
'model': table,
|
||||
'module': module,
|
||||
'res_id': inherit_id.id,
|
||||
'noupdate': noupdate,
|
||||
},context=context)
|
||||
self.create(cr, uid, {
|
||||
self.create(cr, SUPERUSER_ID, {
|
||||
'name': xml_id,
|
||||
'model': model,
|
||||
'module': module,
|
||||
|
||||
@@ -907,6 +907,13 @@ class Environment(object):
|
||||
finally:
|
||||
self.all.recompute = tmp
|
||||
|
||||
@property
|
||||
def recompute_old(self):
|
||||
return self.all.recompute_old
|
||||
|
||||
def clear_recompute_old(self):
|
||||
del self.all.recompute_old[:]
|
||||
|
||||
|
||||
class Environments(object):
|
||||
""" A common object for all environments in a request. """
|
||||
@@ -915,6 +922,7 @@ class Environments(object):
|
||||
self.todo = {} # recomputations {field: [records]}
|
||||
self.mode = False # flag for draft/onchange
|
||||
self.recompute = True
|
||||
self.recompute_old = [] # list of old api compute fields to recompute
|
||||
|
||||
def add(self, env):
|
||||
""" Add the environment `env`. """
|
||||
|
||||
+1
-4
@@ -1054,10 +1054,7 @@ class Float(Field):
|
||||
@property
|
||||
def digits(self):
|
||||
if callable(self._digits):
|
||||
# retrieve a cursor from any environment
|
||||
from openerp.api import Environment
|
||||
cr = next(iter(Environment.envs)).cr
|
||||
return self._digits(cr)
|
||||
return self._digits(fields.get_cursor())
|
||||
else:
|
||||
return self._digits
|
||||
|
||||
|
||||
+2
-1
@@ -907,7 +907,8 @@ class Model(object):
|
||||
raise Exception("Access denied")
|
||||
mod = request.registry[self.model]
|
||||
meth = getattr(mod, method)
|
||||
cr = request.cr
|
||||
# make sure to instantiate an environment
|
||||
cr = request.env.cr
|
||||
result = meth(cr, request.uid, *args, **kw)
|
||||
# reorder read
|
||||
if method == "read":
|
||||
|
||||
+14
-7
@@ -4004,10 +4004,10 @@ class BaseModel(object):
|
||||
recs.invalidate_cache(['parent_left', 'parent_right'])
|
||||
|
||||
result += self._store_get_values(cr, user, ids, vals.keys(), context)
|
||||
result.sort()
|
||||
|
||||
done = {}
|
||||
for order, model_name, ids_to_update, fields_to_recompute in result:
|
||||
recs.env.recompute_old.extend(result)
|
||||
for order, model_name, ids_to_update, fields_to_recompute in sorted(recs.env.recompute_old):
|
||||
key = (model_name, tuple(fields_to_recompute))
|
||||
done.setdefault(key, {})
|
||||
# avoid to do several times the same computation
|
||||
@@ -4018,6 +4018,7 @@ class BaseModel(object):
|
||||
if id not in deleted_related[model_name]:
|
||||
todo.append(id)
|
||||
self.pool[model_name]._store_set_values(cr, user, todo, fields_to_recompute, context)
|
||||
recs.env.clear_recompute_old()
|
||||
|
||||
# recompute new-style fields
|
||||
if recs.env.recompute and context.get('recompute', True):
|
||||
@@ -4267,16 +4268,18 @@ class BaseModel(object):
|
||||
# check Python constraints
|
||||
recs._validate_fields(vals)
|
||||
|
||||
if recs.env.recompute and context.get('recompute', True):
|
||||
result += self._store_get_values(cr, user, [id_new],
|
||||
result += self._store_get_values(cr, user, [id_new],
|
||||
list(set(vals.keys() + self._inherits.values())),
|
||||
context)
|
||||
result.sort()
|
||||
recs.env.recompute_old.extend(result)
|
||||
|
||||
if recs.env.recompute and context.get('recompute', True):
|
||||
done = []
|
||||
for order, model_name, ids, fields2 in result:
|
||||
for order, model_name, ids, fields2 in sorted(recs.env.recompute_old):
|
||||
if not (model_name, ids, fields2) in done:
|
||||
self.pool[model_name]._store_set_values(cr, user, ids, fields2, context)
|
||||
done.append((model_name, ids, fields2))
|
||||
recs.env.clear_recompute_old()
|
||||
# recompute new-style fields
|
||||
recs.recompute()
|
||||
|
||||
@@ -5677,7 +5680,11 @@ class BaseModel(object):
|
||||
while self.env.has_todo():
|
||||
field, recs = self.env.get_todo()
|
||||
# evaluate the fields to recompute, and save them to database
|
||||
names = [f.name for f in field.computed_fields if f.store]
|
||||
names = [
|
||||
f.name
|
||||
for f in field.computed_fields
|
||||
if f.store and self.env.field_todo(f)
|
||||
]
|
||||
for rec in recs:
|
||||
try:
|
||||
values = rec._convert_to_write({
|
||||
|
||||
@@ -173,6 +173,8 @@ class Registry(Mapping):
|
||||
|
||||
:param partial: ``True`` if all models have not been loaded yet.
|
||||
"""
|
||||
lazy_property.reset_all(self)
|
||||
|
||||
# load custom models
|
||||
ir_model = self['ir.model']
|
||||
cr.execute('select model from ir_model where state=%s', ('manual',))
|
||||
|
||||
+9
-2
@@ -78,7 +78,7 @@ class PostgreSQLHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
ct = threading.current_thread()
|
||||
ct_db = getattr(ct, 'dbname', None)
|
||||
dbname = tools.config['log_db'] or ct_db
|
||||
dbname = tools.config['log_db'] if tools.config['log_db'] and tools.config['log_db'] != '%d' else ct_db
|
||||
if not dbname:
|
||||
return
|
||||
with tools.ignore(Exception), tools.mute_logger('openerp.sql_db'), sql_db.db_connect(dbname, allow_uri=True).cursor() as cr:
|
||||
@@ -185,8 +185,15 @@ def init_logger():
|
||||
logging.getLogger().addHandler(handler)
|
||||
|
||||
if tools.config['log_db']:
|
||||
db_levels = {
|
||||
'debug': logging.DEBUG,
|
||||
'info': logging.INFO,
|
||||
'warning': logging.WARNING,
|
||||
'error': logging.ERROR,
|
||||
'critical': logging.CRITICAL,
|
||||
}
|
||||
postgresqlHandler = PostgreSQLHandler()
|
||||
postgresqlHandler.setLevel(25)
|
||||
postgresqlHandler.setLevel(int(db_levels.get(tools.config['log_db_level'], tools.config['log_db_level'])))
|
||||
logging.getLogger().addHandler(postgresqlHandler)
|
||||
|
||||
# Configure loggers levels
|
||||
|
||||
+10
-8
@@ -52,6 +52,14 @@ from openerp.tools import float_repr, float_round, frozendict, html_sanitize
|
||||
import simplejson
|
||||
from openerp import SUPERUSER_ID, registry
|
||||
|
||||
def get_cursor():
|
||||
# retrieve a valid cursor from any environment
|
||||
from openerp.api import Environment
|
||||
for env in Environment.envs:
|
||||
if not env.cr.closed:
|
||||
return env.cr
|
||||
raise RuntimeError("No valid cursor found")
|
||||
|
||||
EMPTY_DICT = frozendict()
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -388,10 +396,7 @@ class float(_column):
|
||||
@property
|
||||
def digits(self):
|
||||
if self._digits_compute:
|
||||
# retrieve a cursor from any environment
|
||||
from openerp.api import Environment
|
||||
cr = next(iter(Environment.envs)).cr
|
||||
return self._digits_compute(cr)
|
||||
return self._digits_compute(get_cursor())
|
||||
else:
|
||||
return self._digits
|
||||
|
||||
@@ -1311,10 +1316,7 @@ class function(_column):
|
||||
@property
|
||||
def digits(self):
|
||||
if self._digits_compute:
|
||||
# retrieve a cursor from any environment
|
||||
from openerp.api import Environment
|
||||
cr = next(iter(Environment.envs)).cr
|
||||
return self._digits_compute(cr)
|
||||
return self._digits_compute(get_cursor())
|
||||
else:
|
||||
return self._digits
|
||||
|
||||
|
||||
@@ -402,6 +402,12 @@ class Cursor(object):
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._obj, name)
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
# NOTE: we cannot use `__getattr__` delegation as we
|
||||
# should not `check` that the cursor is closed
|
||||
return self._obj.closed
|
||||
|
||||
class TestCursor(Cursor):
|
||||
""" A cursor to be used for tests. It keeps the transaction open across
|
||||
several requests, and simulates committing, rolling back, and closing.
|
||||
|
||||
@@ -179,6 +179,7 @@ class configmanager(object):
|
||||
group.add_option('--log-web', action="append_const", dest="log_handler", const="openerp.http:DEBUG", help='shortcut for --log-handler=openerp.http:DEBUG')
|
||||
group.add_option('--log-sql', action="append_const", dest="log_handler", const="openerp.sql_db:DEBUG", help='shortcut for --log-handler=openerp.sql_db:DEBUG')
|
||||
group.add_option('--log-db', dest='log_db', help="Logging database", my_default=False)
|
||||
group.add_option('--log-db-level', dest='log_db_level', my_default='warning', help="Logging database level")
|
||||
# For backward-compatibility, map the old log levels to something
|
||||
# quite close.
|
||||
levels = [
|
||||
@@ -383,7 +384,7 @@ class configmanager(object):
|
||||
'db_maxconn', 'import_partial', 'addons_path',
|
||||
'xmlrpc', 'syslog', 'without_demo',
|
||||
'dbfilter', 'log_level', 'log_db',
|
||||
'geoip_database',
|
||||
'log_db_level', 'geoip_database',
|
||||
]
|
||||
|
||||
for arg in keys:
|
||||
|
||||
Reference in New Issue
Block a user