[MERGE] forward port branch saas-15 up to b0992d082d
This commit is contained in:
@@ -795,7 +795,7 @@ class AccountBankStatementLine(models.Model):
|
||||
or self.statement_id.journal_id.default_debit_account_id.id,
|
||||
'credit': amount < 0 and -amount or 0.0,
|
||||
'debit': amount > 0 and amount or 0.0,
|
||||
'statement_id': self.statement_id.id,
|
||||
'statement_line_id': self.id,
|
||||
'currency_id': statement_currency != company_currency and statement_currency.id or (st_line_currency != company_currency and st_line_currency.id or False),
|
||||
'amount_currency': amount_currency,
|
||||
}
|
||||
|
||||
@@ -504,9 +504,9 @@ class AccountInvoice(models.Model):
|
||||
else:
|
||||
account_id = pay_account.id
|
||||
payment_term_id = p.property_supplier_payment_term_id.id
|
||||
addr = self.partner_id.address_get(['delivery'])
|
||||
fiscal_position = self.env['account.fiscal.position'].get_fiscal_position(self.partner_id.id, delivery_id=addr['delivery'])
|
||||
|
||||
delivery_partner_id = self.get_delivery_partner_id()
|
||||
fiscal_position = self.env['account.fiscal.position'].get_fiscal_position(self.partner_id.id, delivery_id=delivery_partner_id)
|
||||
|
||||
# If partner has no warning, check its company
|
||||
if p.invoice_warn == 'no-message' and p.parent_id:
|
||||
@@ -534,6 +534,10 @@ class AccountInvoice(models.Model):
|
||||
return {'domain': {'partner_bank_id': [('id', 'in', bank_ids.ids)]}}
|
||||
return {}
|
||||
|
||||
@api.multi
|
||||
def get_delivery_partner_id(self):
|
||||
self.ensure_one()
|
||||
return self.partner_id.address_get(['delivery'])['delivery']
|
||||
|
||||
@api.onchange('journal_id')
|
||||
def _onchange_journal_id(self):
|
||||
@@ -1050,7 +1054,7 @@ class AccountInvoice(models.Model):
|
||||
|
||||
values['invoice_line_ids'] = self._refund_cleanup_lines(invoice.invoice_line_ids)
|
||||
|
||||
tax_lines = filter(lambda l: l.manual, invoice.tax_line_ids)
|
||||
tax_lines = invoice.tax_line_ids
|
||||
values['tax_line_ids'] = self._refund_cleanup_lines(tax_lines)
|
||||
|
||||
if journal_id:
|
||||
|
||||
@@ -304,11 +304,13 @@ class account_journal(models.Model):
|
||||
'default_type': invoice_type,
|
||||
'type': invoice_type
|
||||
})
|
||||
|
||||
[action] = self.env.ref('account.%s' % action_name).read()
|
||||
action['context'] = ctx
|
||||
action['domain'] = self._context.get('use_domain', [])
|
||||
action['views'] = False
|
||||
action['view_id'] = False
|
||||
if action_name in ['action_bank_statement_tree', 'action_view_bank_statement_tree']:
|
||||
action['views'] = False
|
||||
action['view_id'] = False
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
|
||||
@@ -8,6 +8,7 @@ from odoo.exceptions import RedirectWarning, UserError, ValidationError
|
||||
from odoo.tools.misc import formatLang
|
||||
from odoo.tools import float_is_zero, float_compare
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
import odoo.addons.decimal_precision as dp
|
||||
from lxml import etree
|
||||
|
||||
#----------------------------------------------------------
|
||||
@@ -244,9 +245,9 @@ class AccountMove(models.Model):
|
||||
journal_id=journal_id)
|
||||
reversed_moves |= reversed_move
|
||||
#unreconcile all lines reversed
|
||||
aml = ac_move.line_ids.filtered(lambda x: x.account_id.reconcile)
|
||||
aml = ac_move.line_ids.filtered(lambda x: x.account_id.reconcile or x.account_id.internal_type == 'liquidity')
|
||||
aml.remove_move_reconcile()
|
||||
#reconcile together the reconciliable aml and their newly created counterpart
|
||||
#reconcile together the reconciliable and the liquidity aml and their newly created counterpart
|
||||
for account in [x.account_id for x in aml]:
|
||||
to_rec = aml.filtered(lambda y: y.account_id == account)
|
||||
to_rec |= reversed_move.line_ids.filtered(lambda y: y.account_id == account)
|
||||
@@ -370,7 +371,7 @@ class AccountMoveLine(models.Model):
|
||||
self.counterpart = ",".join(counterpart)
|
||||
|
||||
name = fields.Char(string="Label")
|
||||
quantity = fields.Float(digits=(16, 2),
|
||||
quantity = fields.Float(digits=dp.get_precision('Product Unit of Measure'),
|
||||
help="The optional quantity expressed by this line, eg: number of product sold. The quantity is not a legal requirement but is very useful for some reports.")
|
||||
product_uom_id = fields.Many2one('product.uom', string='Unit of Measure')
|
||||
product_id = fields.Many2one('product.product', string='Product')
|
||||
@@ -811,6 +812,11 @@ class AccountMoveLine(models.Model):
|
||||
def _get_pair_to_reconcile(self):
|
||||
#field is either 'amount_residual' or 'amount_residual_currency' (if the reconciled account has a secondary currency set)
|
||||
field = self[0].account_id.currency_id and 'amount_residual_currency' or 'amount_residual'
|
||||
#reconciliation on bank accounts are special cases as we don't want to set them as reconciliable
|
||||
#but we still want to reconcile entries that are reversed together in order to clear those lines
|
||||
#in the bank reconciliation report.
|
||||
if not self[0].account_id.reconcile and self[0].account_id.internal_type == 'liquidity':
|
||||
field = 'balance'
|
||||
rounding = self[0].company_id.currency_id.rounding
|
||||
if self[0].currency_id and all([x.amount_currency and x.currency_id == self[0].currency_id for x in self]):
|
||||
#or if all lines share the same currency
|
||||
@@ -906,7 +912,7 @@ class AccountMoveLine(models.Model):
|
||||
raise UserError(_('To reconcile the entries company should be the same for all entries!'))
|
||||
if len(set(all_accounts)) > 1:
|
||||
raise UserError(_('Entries are not of the same account!'))
|
||||
if not all_accounts[0].reconcile:
|
||||
if not (all_accounts[0].reconcile or all_accounts[0].internal_type == 'liquidity'):
|
||||
raise UserError(_('The account %s (%s) is not marked as reconciliable !') % (all_accounts[0].name, all_accounts[0].code))
|
||||
if len(partners) > 1:
|
||||
raise UserError(_('The partner has to be the same on all lines for receivable and payable accounts!'))
|
||||
@@ -1500,9 +1506,9 @@ class AccountPartialReconcile(models.Model):
|
||||
for rec in self:
|
||||
if not rec.company_id.currency_exchange_journal_id:
|
||||
raise UserError(_("You should configure the 'Exchange Rate Journal' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates."))
|
||||
if not self.company_id.income_currency_exchange_account_id.id:
|
||||
if not rec.company_id.income_currency_exchange_account_id.id:
|
||||
raise UserError(_("You should configure the 'Gain Exchange Rate Account' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates."))
|
||||
if not self.company_id.expense_currency_exchange_account_id.id:
|
||||
if not rec.company_id.expense_currency_exchange_account_id.id:
|
||||
raise UserError(_("You should configure the 'Loss Exchange Rate Account' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates."))
|
||||
|
||||
move = rec.env['account.move'].create(
|
||||
@@ -1552,6 +1558,8 @@ class AccountPartialReconcile(models.Model):
|
||||
#amount is the current cash_basis amount minus the one before the reconciliation
|
||||
amount = line.balance * percentage_after - line.balance * percentage_before
|
||||
rounded_amt = line.company_id.currency_id.round(amount)
|
||||
if float_is_zero(rounded_amt, precision_rounding=line.company_id.currency_id.rounding):
|
||||
continue
|
||||
if line.tax_line_id and line.tax_line_id.use_cash_basis:
|
||||
if not newly_created_move:
|
||||
newly_created_move = self._create_tax_basis_move()
|
||||
|
||||
@@ -11,6 +11,7 @@ class ReportPartnerLedger(models.AbstractModel):
|
||||
|
||||
def _lines(self, data, partner):
|
||||
full_account = []
|
||||
currency = self.env['res.currency']
|
||||
query_get_data = self.env['account.move.line'].with_context(data['form'].get('used_context', {}))._query_get()
|
||||
reconcile_clause = "" if data['form']['reconciled'] else ' AND "account_move_line".reconciled = false '
|
||||
params = [partner.id, tuple(data['computed']['move_state']), tuple(data['computed']['account_ids'])] + query_get_data[2]
|
||||
@@ -40,6 +41,7 @@ class ReportPartnerLedger(models.AbstractModel):
|
||||
)
|
||||
sum += r['debit'] - r['credit']
|
||||
r['progress'] = sum
|
||||
r['currency_id'] = currency.browse(r.get('currency_id'))
|
||||
full_account.append(r)
|
||||
return full_account
|
||||
|
||||
|
||||
@@ -621,7 +621,7 @@
|
||||
<field name="act_window_id" ref="action_bank_statement_tree"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_bank_statement_form_bank">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_bank_statement_form"/>
|
||||
<field name="act_window_id" ref="action_bank_statement_tree"/>
|
||||
|
||||
@@ -125,18 +125,23 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" t-if="len(o.tax_line_ids) > 1">
|
||||
<!-- DO NOT REMOVE THIS TABLE. MANDATORY IN SOME COUNTRIES -->
|
||||
<div class="row" t-if="len(o.tax_line_ids) > 0">
|
||||
<div class="col-xs-6">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tax</th>
|
||||
<th class="text-right">Base</th>
|
||||
<th class="text-right">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="o.tax_line_ids" t-as="t">
|
||||
<td><span t-field="t.tax_id.description"/></td>
|
||||
<td class="text-right">
|
||||
<span t-field="t.base" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="t.amount" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<th>Debit</th>
|
||||
<th>Credit</th>
|
||||
<th>Balance</th>
|
||||
<th t-if="amount_currency">Currency</th>
|
||||
<th t-if="data['form']['amount_currency']">Currency</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -77,8 +77,10 @@
|
||||
<td class="text-right">
|
||||
<span t-esc="line['progress']" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
|
||||
</td>
|
||||
<td t-if="amount_currency">
|
||||
<span t-esc="line['amount_currency']" t-options="{'widget': 'monetary', 'display_currency': line['currency_id']}"/>
|
||||
<td class="text-right" t-if="data['form']['amount_currency']">
|
||||
<t t-if="line['currency_id']">
|
||||
<span t-esc="line['amount_currency']" t-options="{'widget': 'monetary', 'display_currency': line['currency_id']}"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -58,7 +58,6 @@ class AccountInvoiceRefund(models.TransientModel):
|
||||
date = form.date or False
|
||||
description = form.description or inv.name
|
||||
refund = inv.refund(form.date_invoice, date, description, inv.journal_id.id)
|
||||
refund.compute_taxes()
|
||||
|
||||
created_inv.append(refund.id)
|
||||
if mode in ('cancel', 'modify'):
|
||||
|
||||
@@ -471,15 +471,14 @@ class AccountAssetDepreciationLine(models.Model):
|
||||
@api.multi
|
||||
def create_move(self, post_move=True):
|
||||
created_moves = self.env['account.move']
|
||||
prec = self.env['decimal.precision'].precision_get('Account')
|
||||
for line in self:
|
||||
category_id = line.asset_id.category_id
|
||||
depreciation_date = self.env.context.get('depreciation_date') or line.depreciation_date or fields.Date.context_today(self)
|
||||
company_currency = line.asset_id.company_id.currency_id
|
||||
current_currency = line.asset_id.currency_id
|
||||
amount = current_currency.compute(line.amount, company_currency)
|
||||
sign = (category_id.journal_id.type == 'purchase' or category_id.journal_id.type == 'sale' and 1) or -1
|
||||
asset_name = line.asset_id.name + ' (%s/%s)' % (line.sequence, len(line.asset_id.depreciation_line_ids))
|
||||
prec = self.env['decimal.precision'].precision_get('Account')
|
||||
move_line_1 = {
|
||||
'name': asset_name,
|
||||
'account_id': category_id.account_depreciation_id.id,
|
||||
@@ -489,7 +488,7 @@ class AccountAssetDepreciationLine(models.Model):
|
||||
'partner_id': line.asset_id.partner_id.id,
|
||||
'analytic_account_id': category_id.account_analytic_id.id if category_id.type == 'sale' else False,
|
||||
'currency_id': company_currency != current_currency and current_currency.id or False,
|
||||
'amount_currency': company_currency != current_currency and - sign * line.amount or 0.0,
|
||||
'amount_currency': company_currency != current_currency and - 1.0 * line.amount or 0.0,
|
||||
}
|
||||
move_line_2 = {
|
||||
'name': asset_name,
|
||||
@@ -500,7 +499,7 @@ class AccountAssetDepreciationLine(models.Model):
|
||||
'partner_id': line.asset_id.partner_id.id,
|
||||
'analytic_account_id': category_id.account_analytic_id.id if category_id.type == 'purchase' else False,
|
||||
'currency_id': company_currency != current_currency and current_currency.id or False,
|
||||
'amount_currency': company_currency != current_currency and sign * line.amount or 0.0,
|
||||
'amount_currency': company_currency != current_currency and line.amount or 0.0,
|
||||
}
|
||||
move_vals = {
|
||||
'ref': line.asset_id.code,
|
||||
|
||||
@@ -894,7 +894,7 @@ class Lead(models.Model):
|
||||
'nb_opportunities': 0,
|
||||
}
|
||||
|
||||
opportunities = self.search([('type', '=', 'opportunity'), ('user_id', '=', self._uid)])
|
||||
opportunities = self.search([('type', '=', 'opportunity'), ('user_id', '=', self._uid), ('activity_date_deadline', '!=', False)])
|
||||
|
||||
for opp in opportunities:
|
||||
# Expected closing
|
||||
|
||||
@@ -30,7 +30,7 @@ class EventType(models.Model):
|
||||
'interval_unit': 'days',
|
||||
'interval_type': 'before_event',
|
||||
'template_id': self.env.ref('event.event_reminder')
|
||||
})]
|
||||
})] if self.user_has_groups('event.group_email_scheduling') else []
|
||||
|
||||
name = fields.Char('Event Category', required=True, translate=True)
|
||||
# registration
|
||||
@@ -239,7 +239,7 @@ class EventEvent(models.Model):
|
||||
if self.event_type_id.use_reply_to:
|
||||
self.reply_to = self.event_type_id.default_reply_to
|
||||
|
||||
if self.event_type_id.use_reply_to:
|
||||
if self.event_type_id.use_hashtag:
|
||||
self.twitter_hashtag = self.event_type_id.default_hashtag
|
||||
|
||||
if self.event_type_id.use_timezone:
|
||||
|
||||
@@ -77,7 +77,7 @@ class EventMailScheduler(models.Model):
|
||||
if self.interval_type in ['before_event', 'after_event']:
|
||||
self.done = self.mail_sent
|
||||
else:
|
||||
self.done = len(self.mail_registration_ids) == len(self.event_id.registration_ids) and all(filter(lambda line: line.mail_sent, self.mail_registration_ids))
|
||||
self.done = len(self.mail_registration_ids) == len(self.event_id.registration_ids) and all(mail.mail_sent for mail in self.mail_registration_ids)
|
||||
|
||||
@api.one
|
||||
@api.depends('event_id.state', 'event_id.date_begin', 'interval_type', 'interval_unit', 'interval_nbr')
|
||||
|
||||
@@ -172,6 +172,10 @@
|
||||
<field name="name">Attendees</field>
|
||||
<field name="view_mode">tree,form,calendar,graph</field>
|
||||
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id, 'search_default_expected': True}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a new attendee.
|
||||
</p></field>
|
||||
</record>
|
||||
|
||||
<!-- EVENT.EVENT VIEWS -->
|
||||
@@ -231,7 +235,11 @@
|
||||
<group>
|
||||
<field name="event_type_id" options="{'no_create':True}"/>
|
||||
<field name="reply_to" string="Contact Email"/>
|
||||
<field name="twitter_hashtag"/>
|
||||
<label for="twitter_hashtag"/>
|
||||
<div>
|
||||
<span class="oe_inline"># </span>
|
||||
<field name="twitter_hashtag" nolabel="1" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="auto_confirm" groups="base.group_no_one"/>
|
||||
</group>
|
||||
<group>
|
||||
@@ -589,7 +597,7 @@
|
||||
<field name="scheduled_date"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<notebook groups="base.group_no_one">
|
||||
<page string="Registration Mails">
|
||||
<field name="mail_registration_ids">
|
||||
<tree string="Registration mail" editable="bottom">
|
||||
|
||||
@@ -213,11 +213,11 @@ class FleetVehicle(models.Model):
|
||||
LogContract = self.env['fleet.vehicle.log.contract']
|
||||
Cost = self.env['fleet.vehicle.cost']
|
||||
for record in self:
|
||||
record.odometer_count = Odometer.search_count([('vehicle_id', '=', self.id)])
|
||||
record.fuel_logs_count = LogFuel.search_count([('vehicle_id', '=', self.id)])
|
||||
record.service_count = LogService.search_count([('vehicle_id', '=', self.id)])
|
||||
record.contract_count = LogContract.search_count([('vehicle_id', '=', self.id)])
|
||||
record.cost_count = Cost.search_count([('vehicle_id', '=', self.id), ('parent_id', '=', False)])
|
||||
record.odometer_count = Odometer.search_count([('vehicle_id', '=', record.id)])
|
||||
record.fuel_logs_count = LogFuel.search_count([('vehicle_id', '=', record.id)])
|
||||
record.service_count = LogService.search_count([('vehicle_id', '=', record.id)])
|
||||
record.contract_count = LogContract.search_count([('vehicle_id', '=', record.id)])
|
||||
record.cost_count = Cost.search_count([('vehicle_id', '=', record.id), ('parent_id', '=', False)])
|
||||
|
||||
@api.depends('log_contracts')
|
||||
def _compute_contract_reminder(self):
|
||||
|
||||
@@ -172,19 +172,24 @@ class HrExpense(models.Model):
|
||||
'''
|
||||
main function that is called when trying to create the accounting entries related to an expense
|
||||
'''
|
||||
move_group_by_sheet = {}
|
||||
for expense in self:
|
||||
journal = expense.sheet_id.bank_journal_id if expense.payment_mode == 'company_account' else expense.sheet_id.journal_id
|
||||
#create the move that will contain the accounting entries
|
||||
acc_date = expense.sheet_id.accounting_date or expense.date
|
||||
move = self.env['account.move'].create({
|
||||
'journal_id': journal.id,
|
||||
'company_id': self.env.user.company_id.id,
|
||||
'date': acc_date,
|
||||
'ref': expense.sheet_id.name,
|
||||
# force the name to the default value, to avoid an eventual 'default_name' in the context
|
||||
# to set it to '' which cause no number to be given to the account.move when posted.
|
||||
'name': '/',
|
||||
})
|
||||
if not expense.sheet_id.id in move_group_by_sheet:
|
||||
move = self.env['account.move'].create({
|
||||
'journal_id': journal.id,
|
||||
'company_id': self.env.user.company_id.id,
|
||||
'date': acc_date,
|
||||
'ref': expense.sheet_id.name,
|
||||
# force the name to the default value, to avoid an eventual 'default_name' in the context
|
||||
# to set it to '' which cause no number to be given to the account.move when posted.
|
||||
'name': '/',
|
||||
})
|
||||
move_group_by_sheet[expense.sheet_id.id] = move
|
||||
else:
|
||||
move = move_group_by_sheet[expense.sheet_id.id]
|
||||
company_currency = expense.company_id.currency_id
|
||||
diff_currency_p = expense.currency_id != company_currency
|
||||
#one account.move.line per expense (+taxes..)
|
||||
@@ -235,38 +240,46 @@ class HrExpense(models.Model):
|
||||
lines = map(lambda x: (0, 0, expense._prepare_move_line(x)), move_lines)
|
||||
move.with_context(dont_create_taxes=True).write({'line_ids': lines})
|
||||
expense.sheet_id.write({'account_move_id': move.id})
|
||||
move.post()
|
||||
if expense.payment_mode == 'company_account':
|
||||
expense.sheet_id.paid_expense_sheets()
|
||||
for move in move_group_by_sheet.values():
|
||||
move.post()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _prepare_move_line_value(self):
|
||||
self.ensure_one()
|
||||
if self.account_id:
|
||||
account = self.account_id
|
||||
elif self.product_id:
|
||||
account = self.product_id.product_tmpl_id._get_product_accounts()['expense']
|
||||
if not account:
|
||||
raise UserError(
|
||||
_("No Expense account found for the product %s (or for its category), please configure one.") % (self.product_id.name))
|
||||
else:
|
||||
account = self.env['ir.property'].with_context(force_company=self.company_id.id).get('property_account_expense_categ_id', 'product.category')
|
||||
if not account:
|
||||
raise UserError(
|
||||
_('Please configure Default Expense account for Product expense: `property_account_expense_categ_id`.'))
|
||||
aml_name = self.employee_id.name + ': ' + self.name.split('\n')[0][:64]
|
||||
move_line = {
|
||||
'type': 'src',
|
||||
'name': aml_name,
|
||||
'price_unit': self.unit_amount,
|
||||
'quantity': self.quantity,
|
||||
'price': self.total_amount,
|
||||
'account_id': account.id,
|
||||
'product_id': self.product_id.id,
|
||||
'uom_id': self.product_uom_id.id,
|
||||
'analytic_account_id': self.analytic_account_id.id,
|
||||
}
|
||||
return move_line
|
||||
|
||||
@api.multi
|
||||
def _move_line_get(self):
|
||||
account_move = []
|
||||
for expense in self:
|
||||
if expense.account_id:
|
||||
account = expense.account_id
|
||||
elif expense.product_id:
|
||||
account = expense.product_id.product_tmpl_id._get_product_accounts()['expense']
|
||||
if not account:
|
||||
raise UserError(_("No Expense account found for the product %s (or for its category), please configure one.") % (expense.product_id.name))
|
||||
else:
|
||||
account = self.env['ir.property'].with_context(force_company=expense.company_id.id).get('property_account_expense_categ_id', 'product.category')
|
||||
if not account:
|
||||
raise UserError(_('Please configure Default Expense account for Product expense: `property_account_expense_categ_id`.'))
|
||||
|
||||
aml_name = expense.employee_id.name + ': ' + expense.name.split('\n')[0][:64]
|
||||
move_line = {
|
||||
'type': 'src',
|
||||
'name': aml_name,
|
||||
'price_unit': expense.unit_amount,
|
||||
'quantity': expense.quantity,
|
||||
'price': expense.total_amount,
|
||||
'account_id': account.id,
|
||||
'product_id': expense.product_id.id,
|
||||
'uom_id': expense.product_uom_id.id,
|
||||
'analytic_account_id': expense.analytic_account_id.id,
|
||||
}
|
||||
move_line = expense._prepare_move_line_value()
|
||||
account_move.append(move_line)
|
||||
|
||||
# Calculate tax lines and adjust base line
|
||||
|
||||
@@ -10,7 +10,7 @@ class HrTimesheetSheet(models.Model):
|
||||
_inherit = "hr_timesheet_sheet.sheet"
|
||||
|
||||
attendances_ids = fields.One2many('hr.attendance', 'sheet_id', 'Attendances')
|
||||
total_attendance = fields.Integer(string='Total Attendance', compute='_compute_total')
|
||||
total_attendance = fields.Float(string='Total Attendance', compute='_compute_total')
|
||||
total_timesheet = fields.Float(string='Total Timesheet', compute="_compute_total")
|
||||
total_difference = fields.Float(string='Difference', compute="_compute_total")
|
||||
period_ids = fields.One2many('hr_timesheet_sheet.sheet.day', 'sheet_id', string='Period', readonly=True)
|
||||
|
||||
@@ -779,7 +779,7 @@
|
||||
<record id="chart2500" model="account.account.template">
|
||||
<field name="code">2500</field>
|
||||
<field name="reconcile" eval="True"/>
|
||||
<field name="user_type_id" ref="account.data_account_type_receivable"/>
|
||||
<field name="user_type_id" ref="account.data_account_type_non_current_assets"/>
|
||||
<field name="name">Vorsteuer</field>
|
||||
<field name="chart_template_id" ref="austria_chart_template"/>
|
||||
</record>
|
||||
|
||||
@@ -43,55 +43,55 @@
|
||||
Resource: res.partner.title
|
||||
Update partner titles
|
||||
-->
|
||||
<record id="res_partner_title_pvt_ltd" model="res.partner.title">
|
||||
<record id="base.res_partner_title_pvt_ltd" model="res.partner.title">
|
||||
<field name="name">Corporation</field>
|
||||
<field name="shortcut">Corp.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_ltd" model="res.partner.title">
|
||||
<record id="base.res_partner_title_ltd" model="res.partner.title">
|
||||
<field name="name">Limited Company</field>
|
||||
<field name="shortcut">Ltd.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_sal" model="res.partner.title">
|
||||
<record id="base.res_partner_title_sal" model="res.partner.title">
|
||||
<field name="name">Sociedad Anónima Laboral</field>
|
||||
<field name="shortcut">S.A.L.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_asoc" model="res.partner.title">
|
||||
<record id="base.res_partner_title_asoc" model="res.partner.title">
|
||||
<field name="name">Asociation</field>
|
||||
<field name="shortcut">Asoc.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_gov" model="res.partner.title">
|
||||
<record id="base.res_partner_title_gov" model="res.partner.title">
|
||||
<field name="name">Government</field>
|
||||
<field name="shortcut">Gov.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_edu" model="res.partner.title">
|
||||
<record id="base.res_partner_title_edu" model="res.partner.title">
|
||||
<field name="name">Educational Institution</field>
|
||||
<field name="shortcut">Edu.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_indprof" model="res.partner.title">
|
||||
<record id="base.res_partner_title_indprof" model="res.partner.title">
|
||||
<field name="name">Independant Professional</field>
|
||||
<field name="shortcut">Ind. Prof.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_dra" model="res.partner.title">
|
||||
<record id="base.res_partner_title_dra" model="res.partner.title">
|
||||
<field name="name">Doctora</field>
|
||||
<field name="shortcut">Dra.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_msc" model="res.partner.title">
|
||||
<record id="base.res_partner_title_msc" model="res.partner.title">
|
||||
<field name="name">Msc.</field>
|
||||
<field name="shortcut">Msc.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_mba" model="res.partner.title">
|
||||
<record id="base.res_partner_title_mba" model="res.partner.title">
|
||||
<field name="name">MBA</field>
|
||||
<field name="shortcut">MBA</field>
|
||||
</record>
|
||||
<record id="res_partner_title_lic" model="res.partner.title">
|
||||
<record id="base.res_partner_title_lic" model="res.partner.title">
|
||||
<field name="name">Licenciado</field>
|
||||
<field name="shortcut">Lic.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_licda" model="res.partner.title">
|
||||
<record id="base.res_partner_title_licda" model="res.partner.title">
|
||||
<field name="name">Licenciada</field>
|
||||
<field name="shortcut">Licda.</field>
|
||||
</record>
|
||||
<record id="res_partner_title_ing" model="res.partner.title">
|
||||
<record id="base.res_partner_title_ing" model="res.partner.title">
|
||||
<field name="name">Ingeniero/a</field>
|
||||
<field name="shortcut">Ing.</field>
|
||||
</record>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
{
|
||||
'name': 'Indian - Schedule VI Accounting',
|
||||
'version': '2.0',
|
||||
'description': """
|
||||
Indian Accounting: Chart of Account.
|
||||
====================================
|
||||
|
||||
Indian accounting chart and localization.
|
||||
|
||||
Schedule VI chart of account for indian accounting.
|
||||
|
||||
Note: The Schedule VI has been revised by MCA and is applicable for all Balance Sheet made after
|
||||
31st March, 2011. The Format has done away with earlier two options of format of Balance
|
||||
Sheet, now only Vertical format has been permitted Which is Supported By OpenERP.
|
||||
""",
|
||||
'category': 'Localization',
|
||||
'depends': [
|
||||
'account',
|
||||
],
|
||||
'demo': [],
|
||||
'data': [
|
||||
'l10n_in_schedule6_chart.xml',
|
||||
'l10n_in_schedule6_tax_template.xml',
|
||||
'account_chart_template.yml',
|
||||
],
|
||||
'auto_install': False,
|
||||
'installable': True,
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
-
|
||||
!python {model: account.chart.template, id: indian_chart_template_schedule6}: |
|
||||
self[0].try_loading_for_current_company()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,842 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Account Tags -->
|
||||
<record id="st_tag_in_01" model="account.account.tag">
|
||||
<field name="name">Tax to Pay</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_02" model="account.account.tag">
|
||||
<field name="name">C Forms</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_03" model="account.account.tag">
|
||||
<field name="name">C Forms Tax Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_04" model="account.account.tag">
|
||||
<field name="name">C Forms Tax Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_05" model="account.account.tag">
|
||||
<field name="name">Excise Duty</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_06" model="account.account.tag">
|
||||
<field name="name">Excise Duty 12.36%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_07" model="account.account.tag">
|
||||
<field name="name">Excise Duty Collected on Sales</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_08" model="account.account.tag">
|
||||
<field name="name">Education Cess 2% Excise Duty Collected on Sales</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_09" model="account.account.tag">
|
||||
<field name="name">Higher Education Cess 1% Excise Duty Collected on Sales</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_10" model="account.account.tag">
|
||||
<field name="name">Excise Duty Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_11" model="account.account.tag">
|
||||
<field name="name">Education Cess 2% Excise Duty Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_12" model="account.account.tag">
|
||||
<field name="name">Higher Education Cess 1% Excise Duty Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_13" model="account.account.tag">
|
||||
<field name="name">Sales Tax</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_14" model="account.account.tag">
|
||||
<field name="name">Sales Tax 4%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_15" model="account.account.tag">
|
||||
<field name="name">Sales Tax 4% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_16" model="account.account.tag">
|
||||
<field name="name">Sales Tax 4% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_17" model="account.account.tag">
|
||||
<field name="name">Sales Tax 12%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_18" model="account.account.tag">
|
||||
<field name="name">Sales Tax 12% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_19" model="account.account.tag">
|
||||
<field name="name">Sales Tax 12% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_20" model="account.account.tag">
|
||||
<field name="name">Sales Tax 15%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_21" model="account.account.tag">
|
||||
<field name="name">Sales Tax 15% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_22" model="account.account.tag">
|
||||
<field name="name">Sales Tax 15% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_23" model="account.account.tag">
|
||||
<field name="name">Service Tax</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_24" model="account.account.tag">
|
||||
<field name="name">Service Tax 12.36%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_25" model="account.account.tag">
|
||||
<field name="name">Service Tax Collected on Sales of Services</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_26" model="account.account.tag">
|
||||
<field name="name">Education Cess 2% Service Tax Collected on Sales of Services</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_27" model="account.account.tag">
|
||||
<field name="name">Higher Education Cess 1% Service Tax Collected on Sales of Services</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_28" model="account.account.tag">
|
||||
<field name="name">Service Tax Paid on Purchase of Services</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_29" model="account.account.tag">
|
||||
<field name="name">Education Cess 2% Service Tax Paid on Purchase of Services</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_30" model="account.account.tag">
|
||||
<field name="name">Higher Education Cess 1% Service Tax Paid on Purchase of Services</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_31" model="account.account.tag">
|
||||
<field name="name">VAT</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_32" model="account.account.tag">
|
||||
<field name="name">VAT 4%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_33" model="account.account.tag">
|
||||
<field name="name">VAT 4% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_34" model="account.account.tag">
|
||||
<field name="name">VAT 4% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_35" model="account.account.tag">
|
||||
<field name="name">VAT 8%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_36" model="account.account.tag">
|
||||
<field name="name">VAT 8% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_37" model="account.account.tag">
|
||||
<field name="name">VAT 8% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_38" model="account.account.tag">
|
||||
<field name="name">VAT 10%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_39" model="account.account.tag">
|
||||
<field name="name">VAT 10% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_40" model="account.account.tag">
|
||||
<field name="name">VAT 10% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_41" model="account.account.tag">
|
||||
<field name="name">VAT 12.5%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_42" model="account.account.tag">
|
||||
<field name="name">VAT 12.5% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_43" model="account.account.tag">
|
||||
<field name="name">VAT 12.5% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_44" model="account.account.tag">
|
||||
<field name="name">Additional VAT 1%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_45" model="account.account.tag">
|
||||
<field name="name">Additional VAT 1% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_46" model="account.account.tag">
|
||||
<field name="name">Additional VAT 1% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_47" model="account.account.tag">
|
||||
<field name="name">Additional VAT 2.5%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_48" model="account.account.tag">
|
||||
<field name="name">Additional VAT 2.5% Collected on Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_49" model="account.account.tag">
|
||||
<field name="name">Additional VAT 2.5% Paid on Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_50" model="account.account.tag">
|
||||
<field name="name">Tax Bases</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_51" model="account.account.tag">
|
||||
<field name="name">Base C Forms</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_52" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_53" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_54" model="account.account.tag">
|
||||
<field name="name">Base Excise Duty</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_55" model="account.account.tag">
|
||||
<field name="name">Base Excise Duty 12.36%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_56" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_57" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_58" model="account.account.tag">
|
||||
<field name="name">Base Sales Tax</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_59" model="account.account.tag">
|
||||
<field name="name">Base Sales Tax 4%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_60" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_61" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_62" model="account.account.tag">
|
||||
<field name="name">Base Sales Tax 12%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_63" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_64" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_65" model="account.account.tag">
|
||||
<field name="name">Base Sales Tax 15%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_66" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_67" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_68" model="account.account.tag">
|
||||
<field name="name">Base Service Tax</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_69" model="account.account.tag">
|
||||
<field name="name">Base Service Tax 12.36%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_70" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_71" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_72" model="account.account.tag">
|
||||
<field name="name">Base VAT</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_73" model="account.account.tag">
|
||||
<field name="name">Base VAT 4%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_74" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_75" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_76" model="account.account.tag">
|
||||
<field name="name">Base VAT 8%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_77" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_78" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_79" model="account.account.tag">
|
||||
<field name="name">Base VAT 10%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_80" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_81" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_82" model="account.account.tag">
|
||||
<field name="name">Base VAT 12.5%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_83" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_84" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_85" model="account.account.tag">
|
||||
<field name="name">Base Additional VAT 1%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_86" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_87" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_88" model="account.account.tag">
|
||||
<field name="name">Base Additional VAT 2.5%</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_89" model="account.account.tag">
|
||||
<field name="name">Base of Sale</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
|
||||
<record id="st_tag_in_90" model="account.account.tag">
|
||||
<field name="name">Base of Purchase</field>
|
||||
<field name="applicability">taxes</field>
|
||||
</record>
|
||||
<!-- Account Tax Templates -->
|
||||
|
||||
<record id="input_tax_15" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Sales Tax @ 15%</field>
|
||||
<field name="description">(schedule6)Input Sales Tax @ 15%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">15</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c114214"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_21'), ref('st_tag_in_66')])]"/>
|
||||
</record>
|
||||
<record id="input_tax_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Sales Tax @ 12%</field>
|
||||
<field name="description">(schedule6)Input Sales Tax @ 12%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c114214"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_18'), ref('st_tag_in_63')])]"/>
|
||||
</record>
|
||||
<record id="input_tax_4" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Sales Tax @ 4%</field>
|
||||
<field name="description">(schedule6)Input Sales Tax @ 4%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">4</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c114214"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_15'), ref('st_tag_in_60')])]"/>
|
||||
</record>
|
||||
<record id="add_input_vat_1" model="account.tax.template">
|
||||
<field name="name">(schedule6)Additional Input VAT @ 1%</field>
|
||||
<field name="description">(schedule6)Additional Input VAT @ 1%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">1</field>
|
||||
<field name="sequence">15</field>
|
||||
<field name="account_id" ref="c114215"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_86'), ref('st_tag_in_45')])]"/>
|
||||
</record>
|
||||
<record id="input_vat_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input VAT @ 12.5%</field>
|
||||
<field name="description">(schedule6)Input VAT @ 12.5%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">12.5</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c114215"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_83'), ref('st_tag_in_42')])]"/>
|
||||
</record>
|
||||
<record id="add_input_vat_2" model="account.tax.template">
|
||||
<field name="name">(schedule6)Additional Input VAT @ 2.5%</field>
|
||||
<field name="description">(schedule6)Additional Input VAT @ 2.5%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">2.5</field>
|
||||
<field name="sequence">15</field>
|
||||
<field name="account_id" ref="c114215"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_89'), ref('st_tag_in_48')])]"/>
|
||||
</record>
|
||||
<record id="sale_vat_8" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input VAT @ 8%</field>
|
||||
<field name="description">(schedule6)Input VAT @ 8%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">8</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c114215"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_77'), ref('st_tag_in_36')])]"/>
|
||||
</record>
|
||||
<record id="sale_vat_10" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input VAT @ 10%</field>
|
||||
<field name="description">(schedule6)Input VAT @ 10%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">10</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c114215"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_39'), ref('st_tag_in_80')])]"/>
|
||||
</record>
|
||||
<record id="sale_tax_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Tax 12%</field>
|
||||
<field name="description">(schedule6)Input Tax 12%</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="account_id" ref="c1142111"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_07')])]"/>
|
||||
</record>
|
||||
<record id="sale_edu_cess_Excise_Duty_2" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Education Cess @ 2% On Excise Duty</field>
|
||||
<field name="description">(schedule6)Input Education Cess @ 2% On Excise Duty</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">0.24</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="account_id" ref="c1142112"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_08')])]"/>
|
||||
</record>
|
||||
<record id="sale_hedu_cess_Excise_Duty_1" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Higher Education Cess @ 1% On Excise Duty</field>
|
||||
<field name="description">(schedule6)Input Higher Education Cess @ 1% On Excise Duty</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">0.1224</field>
|
||||
<field name="sequence">3</field>
|
||||
<field name="account_id" ref="c1142113"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_09')])]"/>
|
||||
</record>
|
||||
<record id="sale_Excise_Duty_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Excise Duty @ 12.36%</field>
|
||||
<field name="description">(schedule6)Input Excise Duty @ 12.36%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">group</field>
|
||||
<field name="amount">0</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="account_id" ref="c1142111"/>
|
||||
<field name="children_tax_ids" eval="[(6, 0, [ref('sale_tax_12'),ref('sale_edu_cess_Excise_Duty_2'),ref('sale_hedu_cess_Excise_Duty_1')])]"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_56')])]"/>
|
||||
</record>
|
||||
<record id="sale_service_tax12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Service Tax 12%</field>
|
||||
<field name="description">(schedule6)Input Service Tax 12%</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="sequence">13</field>
|
||||
<field name="account_id" ref="c1142121"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_25')])]"/>
|
||||
</record>
|
||||
<record id="sale_edu_cess_service_tax_2" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Education Cess @ 2% On Service Tax</field>
|
||||
<field name="description">(schedule6)Input Education Cess @ 2% On Service Tax</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">0.24</field>
|
||||
<field name="sequence">14</field>
|
||||
<field name="account_id" ref="c1142122"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_26')])]"/>
|
||||
</record>
|
||||
<record id="sale_high_edu_service_tax_1" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Higher Education Cess @ 1% On Service Tax</field>
|
||||
<field name="description">(schedule6)Input Higher Education Cess @ 1% On Service Tax</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">0.1224</field>
|
||||
<field name="sequence">15</field>
|
||||
<field name="account_id" ref="c1142123"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_27')])]"/>
|
||||
</record>
|
||||
<record id="sale_service_tax_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input Service Tax @ 12.36%</field>
|
||||
<field name="description">(schedule6)Input Service Tax @ 12.36%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">group</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="include_base_amount">True</field>
|
||||
<field name="sequence">8</field>
|
||||
<field name="account_id" ref="c1142121"/>
|
||||
<field name="children_tax_ids" eval="[(6, 0, [ref('sale_service_tax12'),ref('sale_edu_cess_service_tax_2'),ref('sale_high_edu_service_tax_1')])]"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_70')])]"/>
|
||||
</record>
|
||||
<record id="input_vat_4" model="account.tax.template">
|
||||
<field name="name">(schedule6)Input VAT @ 4%</field>
|
||||
<field name="description">(schedule6)Input VAT @ 4%</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">4</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c114215"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_33'), ref('st_tag_in_74')])]"/>
|
||||
</record>
|
||||
|
||||
<!--output purchase tax-->
|
||||
<record id="output_tax_15" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Purchase Tax @ 15%</field>
|
||||
<field name="description">(schedule6)Output Purchase Tax @ 15%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">15</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c121610"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_22'), ref('st_tag_in_67')])]"/>
|
||||
</record>
|
||||
<record id="output_tax_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Purchase Tax @ 12%</field>
|
||||
<field name="description">(schedule6)Output Purchase Tax @ 12%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c121610"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('st_tag_in_19'), ref('st_tag_in_64')])]"/>
|
||||
</record>
|
||||
<record id="output_tax_4" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Purchase Tax @ 4%</field>
|
||||
<field name="description">(schedule6)Output Purchase Tax @ 4%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">4</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c121610"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_61'), ref('st_tag_in_16')])]"/>
|
||||
</record>
|
||||
<record id="add_output_vat_1" model="account.tax.template">
|
||||
<field name="name">(schedule6)Additional Output VAT @ 1%</field>
|
||||
<field name="description">(schedule6)Additional Output VAT @ 1%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">1</field>
|
||||
<field name="sequence">15</field>
|
||||
<field name="account_id" ref="c121611"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_87'), ref('st_tag_in_46')])]"/>
|
||||
</record>
|
||||
<record id="output_vat_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output VAT @ 12.5%</field>
|
||||
<field name="description">(schedule6)Output VAT @ 12.5%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">12.5</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c121611"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_43'), ref('st_tag_in_84')])]"/>
|
||||
</record>
|
||||
<record id="add_output_vat_2" model="account.tax.template">
|
||||
<field name="name">(schedule6)Additional Output VAT @ 2.5%</field>
|
||||
<field name="description">(schedule6)Additional Output VAT @ 2.5%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">2.5</field>
|
||||
<field name="sequence">15</field>
|
||||
<field name="account_id" ref="c121611"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_90'), ref('st_tag_in_49')])]"/>
|
||||
</record>
|
||||
<record id="purchase_vat_8" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output VAT @ 8%</field>
|
||||
<field name="description">(schedule6)Output VAT @ 8%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">8</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c121611"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_78'), ref('st_tag_in_37')])]"/>
|
||||
</record>
|
||||
<record id="purchase_vat_10" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output VAT @ 10%</field>
|
||||
<field name="description">(schedule6)Output VAT @ 10%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">10</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c121611"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_81'), ref('st_tag_in_40')])]"/>
|
||||
</record>
|
||||
<record id="purchase_edu_cess_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Tax 12%</field>
|
||||
<field name="description">(schedule6)Output Tax 12%</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="account_id" ref="c1216121"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_10')])]"/>
|
||||
</record>
|
||||
<record id="purchase_edu_cess_Excise_Duty_2" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Education Cess @ 2% Excise Duty</field>
|
||||
<field name="description">(schedule6)Output Education Cess @ 2% Excise Duty</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">0.24</field>
|
||||
<field name="sequence">3</field>
|
||||
<field name="account_id" ref="c1216122"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_11')])]"/>
|
||||
</record>
|
||||
<record id="purchase_hedu_cess_Excise_Duty_1" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Higher Education Cess @ 1% Excise Duty</field>
|
||||
<field name="description">(schedule6)Output Higher Education Cess @ 1% Excise Duty</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">0.1224</field>
|
||||
<field name="sequence">4</field>
|
||||
<field name="account_id" ref="c1216123"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_12')])]"/>
|
||||
</record>
|
||||
<record id="purchase_Excise_Duty_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Excise Duty @ 12.36%</field>
|
||||
<field name="description">(schedule6)Output Excise Duty @ 12.36%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">group</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="include_base_amount">True</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="account_id" ref="c1216121"/>
|
||||
<field name="children_tax_ids" eval="[(6, 0, [ref('purchase_edu_cess_12'),ref('purchase_edu_cess_Excise_Duty_2'),ref('purchase_hedu_cess_Excise_Duty_1')])]"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_57')])]"/>
|
||||
</record>
|
||||
<record id="purchase_edu_service_tax12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Service Tax 12%</field>
|
||||
<field name="description">(schedule6)Output Service Tax 12%</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="sequence">9</field>
|
||||
<field name="account_id" ref="c1216131"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_28')])]"/>
|
||||
</record>
|
||||
<record id="purchase_edu_cess_service_tax_2" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Education Cess @ 2% On Service Tax</field>
|
||||
<field name="description">(schedule6)Output Education Cess @ 2% On Service Tax</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">0.24</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c1216132"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_29')])]"/>
|
||||
</record>
|
||||
<record id="purchase_high_edu_service_tax_1" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Higher Education Cess @ 1% On Service Tax</field>
|
||||
<field name="description">(schedule6)Output Higher Education Cess @ 1% On Service Tax</field>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">0.1224</field>
|
||||
<field name="sequence">11</field>
|
||||
<field name="account_id" ref="c1216133"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_30')])]"/>
|
||||
</record>
|
||||
<record id="st_purchase_service_tax_12" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output Service Tax @ 12.36%</field>
|
||||
<field name="description">(schedule6)Output Service Tax @ 12.36%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="include_base_amount">True</field>
|
||||
<field name="amount_type">group</field>
|
||||
<field name="amount">12</field>
|
||||
<field name="sequence">8</field>
|
||||
<field name="account_id" ref="c1216131"/>
|
||||
<field name="children_tax_ids" eval="[(6, 0, [ref('purchase_edu_service_tax12'),ref('purchase_edu_cess_service_tax_2'),ref('purchase_high_edu_service_tax_1')])]"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_71')])]"/>
|
||||
</record>
|
||||
<record id="output_vat_4" model="account.tax.template">
|
||||
<field name="name">(schedule6)Output VAT @ 4%</field>
|
||||
<field name="description">(schedule6)Output VAT @ 4%</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="amount">4</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="account_id" ref="c121611"/>
|
||||
<field name="chart_template_id" ref="indian_chart_template_schedule6"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('st_tag_in_34'), ref('st_tag_in_75')])]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -1696,9 +1696,10 @@ class MailThread(models.AbstractModel):
|
||||
return self._message_post_process_attachments(attachments, attachment_ids, {'model': attach_model, 'res_id': attach_res_id})
|
||||
|
||||
def _message_post_process_attachments(self, attachments, attachment_ids, message_data):
|
||||
IrAttachment, parameter_attachments = self.env['ir.attachment'], self.env['ir.attachment']
|
||||
IrAttachment = self.env['ir.attachment']
|
||||
m2m_attachment_ids = []
|
||||
cid_mapping = {}
|
||||
fname_mapping = {}
|
||||
if attachment_ids:
|
||||
filtered_attachment_ids = self.env['ir.attachment'].sudo().search([
|
||||
('res_model', '=', 'mail.compose.message'),
|
||||
@@ -1714,9 +1715,7 @@ class MailThread(models.AbstractModel):
|
||||
name, content = attachment
|
||||
elif len(attachment) == 3:
|
||||
name, content, info = attachment
|
||||
if info and info.get('cid'):
|
||||
cid = info['cid']
|
||||
cid_mapping[cid] = name
|
||||
cid = info and info.get('cid')
|
||||
else:
|
||||
continue
|
||||
if isinstance(content, unicode):
|
||||
@@ -1724,13 +1723,16 @@ class MailThread(models.AbstractModel):
|
||||
data_attach = {
|
||||
'name': name,
|
||||
'datas': base64.b64encode(str(content)),
|
||||
'datas_fname': cid or name,
|
||||
'datas_fname': name,
|
||||
'description': name,
|
||||
'res_model': message_data['model'],
|
||||
'res_id': message_data['res_id'],
|
||||
}
|
||||
parameter_attachments |= IrAttachment.create(data_attach)
|
||||
m2m_attachment_ids += [(4, attach.id) for attach in parameter_attachments]
|
||||
new_attachment = IrAttachment.create(data_attach)
|
||||
m2m_attachment_ids.append((4, new_attachment.id))
|
||||
if cid:
|
||||
cid_mapping[cid] = new_attachment
|
||||
fname_mapping[name] = new_attachment
|
||||
|
||||
if cid_mapping and message_data.get('body'):
|
||||
root = lxml.html.fromstring(tools.ustr(message_data['body']))
|
||||
@@ -1738,12 +1740,11 @@ class MailThread(models.AbstractModel):
|
||||
for node in root.iter('img'):
|
||||
if node.get('src', '').startswith('cid:'):
|
||||
cid = node.get('src').split('cid:')[1]
|
||||
fname = cid_mapping.get(cid, node.get('data-filename', ''))
|
||||
attachment = parameter_attachments.filtered(lambda attachment: attachment.datas_fname == cid)
|
||||
attachment = cid_mapping.get(cid)
|
||||
if not attachment:
|
||||
attachment = parameter_attachments.filtered(lambda attachment: attachment.datas_fname == fname)
|
||||
attachment = fname_mapping.get(node.get('data-filename'), '')
|
||||
if attachment:
|
||||
node.set('src', '/web/image/%s' % attachment.ids[0])
|
||||
node.set('src', '/web/image/%s' % attachment.id)
|
||||
postprocessed = True
|
||||
if postprocessed:
|
||||
body = lxml.html.tostring(root, pretty_print=False, encoding='UTF-8')
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
<field name="owner_user_id" string="Owner"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="maintenance_team_id"/>
|
||||
<field name="maintenance_team_id" attrs="{'required': [('period', '!=', 0)]}"/>
|
||||
<field name="technician_user_id"/>
|
||||
<field name="assign_date" groups="base.group_no_one"/>
|
||||
<field name="scrap_date" groups="base.group_no_one"/>
|
||||
|
||||
@@ -7,8 +7,7 @@ import werkzeug.urls
|
||||
|
||||
from odoo import api, fields, models, tools
|
||||
|
||||
|
||||
URL_REGEX = r'(\bhref=[\'"]([^\'"]+)[\'"])'
|
||||
from openerp.addons.link_tracker.models.link_tracker import URL_REGEX
|
||||
|
||||
|
||||
class MailMail(models.Model):
|
||||
|
||||
@@ -44,7 +44,12 @@ class ProductProduct(models.Model):
|
||||
read_group_res = self.env['mrp.bom'].read_group([('product_id', 'in', self.ids)], ['product_id'], ['product_id'])
|
||||
mapped_data = dict([(data['product_id'][0], data['product_id_count']) for data in read_group_res])
|
||||
for product in self:
|
||||
product.bom_count = mapped_data.get(product.id, 0)
|
||||
if product.product_tmpl_id.product_variant_count == 1:
|
||||
bom_count = mapped_data.get(product.id, product.product_tmpl_id.bom_count)
|
||||
else:
|
||||
bom_count = mapped_data.get(product.id, 0)
|
||||
product.bom_count = bom_count
|
||||
|
||||
|
||||
def _compute_mo_count(self):
|
||||
read_group_res = self.env['mrp.production'].read_group([('product_id', 'in', self.ids)], ['product_id'], ['product_id'])
|
||||
|
||||
@@ -33,7 +33,7 @@ class StockMoveLots(models.Model):
|
||||
def _check_lot_id(self):
|
||||
if self.move_id.product_id.tracking == 'serial':
|
||||
lots = set([])
|
||||
for move_lot in self.move_id.move_lot_ids.filtered(lambda r: not r.lot_produced_id):
|
||||
for move_lot in self.move_id.active_move_lot_ids.filtered(lambda r: not r.lot_produced_id and r.lot_id):
|
||||
if move_lot.lot_id in lots:
|
||||
raise exceptions.UserError(_('You cannot use the same serial number in two different lines.'))
|
||||
if float_compare(move_lot.quantity_done, 1.0, precision_rounding=move_lot.product_id.uom_id.rounding) == 1:
|
||||
@@ -59,6 +59,15 @@ class StockMoveLots(models.Model):
|
||||
self.quantity_done = self.quantity_done - 1
|
||||
return self.move_id.split_move_lot()
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if 'lot_id' in vals:
|
||||
for movelot in self:
|
||||
movelot.move_id.production_id.move_raw_ids.mapped('move_lot_ids')\
|
||||
.filtered(lambda r: r.done_wo and not r.done_move and r.lot_produced_id == movelot.lot_id)\
|
||||
.write({'lot_produced_id': vals['lot_id']})
|
||||
return super(StockMoveLots, self).write(vals)
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = 'stock.move'
|
||||
|
||||
@@ -520,7 +520,10 @@ class RepairLine(models.Model):
|
||||
if not self.product_id or not self.product_uom_qty:
|
||||
return
|
||||
if self.product_id:
|
||||
self.name = self.product_id.display_name
|
||||
if partner:
|
||||
self.name = self.product_id.with_context(lang=partner.lang).display_name
|
||||
else:
|
||||
self.name = self.product_id.display_name
|
||||
self.product_uom = self.product_id.uom_id.id
|
||||
if self.type != 'remove':
|
||||
if partner and self.product_id:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
string="Quotation / Order"
|
||||
id="action_report_mrp_repair_order"
|
||||
model="mrp.repair"
|
||||
name="mrp_repair.report_mrprepairorder"
|
||||
name="mrp_repair.report_mrprepairorder2"
|
||||
file="mrp_repair.report_mrprepairorder"
|
||||
report_type="qweb-pdf"
|
||||
/>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<odoo>
|
||||
<data>
|
||||
<template id="report_mrprepairorder">
|
||||
<t t-call="report.html_container">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<t t-call="report.external_layout">
|
||||
<t t-set="o" t-value="o.with_context({'lang': o.partner_id.lang})" />
|
||||
<div class="page">
|
||||
<div class="oe_structure"/>
|
||||
|
||||
@@ -156,6 +156,13 @@
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="report_mrprepairorder2">
|
||||
<t t-call="report.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="mrp_repair.report_mrprepairorder" t-lang="doc.partner_id.lang"/>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</data>
|
||||
|
||||
@@ -150,7 +150,7 @@ class AuthorizeAPI():
|
||||
etree.SubElement(root, "transId").text = transaction_id
|
||||
customer = etree.SubElement(root, "customer")
|
||||
etree.SubElement(customer, "merchantCustomerId").text = 'ODOO-%s-%s' % (partner.id, uuid4().hex[:8])
|
||||
etree.SubElement(customer, "email").text = partner.email
|
||||
etree.SubElement(customer, "email").text = partner.email or ''
|
||||
response = self._authorize_request(root)
|
||||
res = dict()
|
||||
res['profile_id'] = response.find('customerProfileId').text
|
||||
|
||||
@@ -32,16 +32,22 @@ class PaypalController(http.Controller):
|
||||
|
||||
:param response str: text response, structured in the following way:
|
||||
STATUS\nkey1=value1\nkey2=value2...\n
|
||||
or STATUS\nError message...\n
|
||||
:rtype tuple(str, dict)
|
||||
:return: tuple containing the STATUS str and the key/value pairs
|
||||
parsed as a dict
|
||||
"""
|
||||
lines = filter(None, response.split('\n'))
|
||||
status = lines.pop(0)
|
||||
pdt_post = dict(line.split('=', 1) for line in lines)
|
||||
# html unescape
|
||||
for post in pdt_post:
|
||||
pdt_post[post] = urllib.unquote_plus(pdt_post[post]).decode('utf8')
|
||||
|
||||
pdt_post = {}
|
||||
for line in lines:
|
||||
split = line.split('=', 1)
|
||||
if len(split) == 2:
|
||||
pdt_post[split[0]] = urllib.unquote_plus(split[1]).decode('utf8')
|
||||
else:
|
||||
_logger.warning('Paypal: error processing pdt response: %s', line)
|
||||
|
||||
return status, pdt_post
|
||||
|
||||
def paypal_validate_data(self, **post):
|
||||
|
||||
@@ -14,7 +14,10 @@ class PosController(http.Controller):
|
||||
@http.route('/pos/web', type='http', auth='user')
|
||||
def pos_web(self, debug=False, **k):
|
||||
# if user not logged in, log him in
|
||||
pos_sessions = request.env['pos.session'].search([('state', '=', 'opened'), ('user_id', '=', request.session.uid)])
|
||||
pos_sessions = request.env['pos.session'].search([
|
||||
('state', '=', 'opened'),
|
||||
('user_id', '=', request.session.uid),
|
||||
('name', 'not like', '(RESCUE FOR')])
|
||||
if not pos_sessions:
|
||||
return werkzeug.utils.redirect('/web#action=point_of_sale.action_client_pos_menu')
|
||||
pos_sessions.login()
|
||||
|
||||
@@ -31,7 +31,7 @@ class PosConfig(models.Model):
|
||||
|
||||
def _default_sale_journal(self):
|
||||
journal = self.env.ref('point_of_sale.pos_sale_journal', raise_if_not_found=False)
|
||||
if journal and journal.company_id == self.env.user.company_id:
|
||||
if journal and journal.sudo().company_id == self.env.user.company_id:
|
||||
return journal
|
||||
return self._default_invoice_journal()
|
||||
|
||||
@@ -146,9 +146,12 @@ class PosConfig(models.Model):
|
||||
@api.depends('session_ids')
|
||||
def _compute_current_session(self):
|
||||
for pos_config in self:
|
||||
session = pos_config.session_ids.filtered(lambda r: r.user_id.id == self.env.uid and not r.state == 'closed')
|
||||
pos_config.current_session_id = session
|
||||
pos_config.current_session_state = session.state
|
||||
session = pos_config.session_ids.filtered(lambda r: r.user_id.id == self.env.uid and \
|
||||
not r.state == 'closed' and \
|
||||
'(RESCUE FOR' not in r.name)
|
||||
# sessions ordered by id desc
|
||||
pos_config.current_session_id = session and session[0].id or False
|
||||
pos_config.current_session_state = session and session[0].state or False
|
||||
|
||||
@api.depends('session_ids')
|
||||
def _compute_last_session(self):
|
||||
@@ -168,7 +171,8 @@ class PosConfig(models.Model):
|
||||
@api.depends('session_ids')
|
||||
def _compute_current_session_user(self):
|
||||
for pos_config in self:
|
||||
pos_config.pos_session_username = pos_config.session_ids.filtered(lambda s: s.state == 'opened').user_id.name
|
||||
session = pos_config.session_ids.filtered(lambda s: s.state == 'opened' and '(RESCUE FOR' not in s.name)
|
||||
pos_config.pos_session_username = session and session[0].user_id.name or False
|
||||
|
||||
@api.constrains('company_id', 'stock_location_id')
|
||||
def _check_company_location(self):
|
||||
@@ -216,7 +220,7 @@ class PosConfig(models.Model):
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
IrSequence = self.env['ir.sequence']
|
||||
IrSequence = self.env['ir.sequence'].sudo()
|
||||
val = {
|
||||
'name': _('POS Order %s') % values['name'],
|
||||
'padding': 4,
|
||||
|
||||
@@ -66,11 +66,18 @@ class PosOrder(models.Model):
|
||||
closed_session.id,
|
||||
order['name'],
|
||||
order['amount_total'])
|
||||
rescue_session = PosSession.search([
|
||||
('name', 'like', '(RESCUE FOR %(session)s)' % {'session': closed_session.name}),
|
||||
('state', 'not in', ('closed', 'closing_control')),
|
||||
], limit=1)
|
||||
if rescue_session:
|
||||
_logger.warning('reusing recovery session %s for saving order %s', rescue_session.name, order['name'])
|
||||
return rescue_session
|
||||
|
||||
_logger.warning('attempting to create recovery session for saving order %s', order['name'])
|
||||
new_session = PosSession.create({
|
||||
'config_id': closed_session.config_id.id,
|
||||
'name': _('(RESCUE FOR %(session)s)') % {'session': closed_session.name},
|
||||
'rescue': True, # avoid conflict with live sessions
|
||||
'name': '(RESCUE FOR %(session)s)' % {'session': closed_session.name},
|
||||
})
|
||||
# bypass opening_control (necessary when using cash control)
|
||||
new_session.action_pos_session_open()
|
||||
@@ -347,7 +354,12 @@ class PosOrder(models.Model):
|
||||
name = fields.Char(string='Order Ref', required=True, readonly=True, copy=False, default='/')
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, default=lambda self: self.env.user.company_id)
|
||||
date_order = fields.Datetime(string='Order Date', readonly=True, index=True, default=fields.Datetime.now)
|
||||
user_id = fields.Many2one('res.users', string='Salesman', help="Person who uses the cash register. It can be a reliever, a student or an interim employee.", default=lambda self: self.env.uid)
|
||||
user_id = fields.Many2one(
|
||||
comodel_name='res.users', string='Salesman',
|
||||
help="Person who uses the cash register. It can be a reliever, a student or an interim employee.",
|
||||
default=lambda self: self.env.uid,
|
||||
states={'done': [('readonly', True)], 'invoiced': [('readonly', True)]},
|
||||
)
|
||||
amount_tax = fields.Float(compute='_compute_amount_all', string='Taxes', digits=0)
|
||||
amount_total = fields.Float(compute='_compute_amount_all', string='Total', digits=0)
|
||||
amount_paid = fields.Float(compute='_compute_amount_all', string='Paid', states={'draft': [('readonly', False)]}, readonly=True, digits=0)
|
||||
@@ -372,12 +384,22 @@ class PosOrder(models.Model):
|
||||
account_move = fields.Many2one('account.move', string='Journal Entry', readonly=True, copy=False)
|
||||
picking_id = fields.Many2one('stock.picking', string='Picking', readonly=True, copy=False)
|
||||
picking_type_id = fields.Many2one('stock.picking.type', related='session_id.config_id.picking_type_id', string="Operation Type")
|
||||
location_id = fields.Many2one('stock.location', related='session_id.config_id.stock_location_id', string="Location", store=True)
|
||||
location_id = fields.Many2one(
|
||||
comodel_name='stock.location',
|
||||
related='session_id.config_id.stock_location_id',
|
||||
string="Location", store=True,
|
||||
readonly=True,
|
||||
)
|
||||
note = fields.Text(string='Internal Notes')
|
||||
nb_print = fields.Integer(string='Number of Print', readonly=True, copy=False, default=0)
|
||||
pos_reference = fields.Char(string='Receipt Ref', readonly=True, copy=False)
|
||||
sale_journal = fields.Many2one('account.journal', related='session_id.config_id.journal_id', string='Sales Journal', store=True, readonly=True)
|
||||
fiscal_position_id = fields.Many2one('account.fiscal.position', string='Fiscal Position', default=lambda self: self._default_session().config_id.default_fiscal_position_id)
|
||||
fiscal_position_id = fields.Many2one(
|
||||
comodel_name='account.fiscal.position', string='Fiscal Position',
|
||||
default=lambda self: self._default_session().config_id.default_fiscal_position_id,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
)
|
||||
|
||||
@api.depends('statement_ids', 'lines.price_subtotal_incl', 'lines.discount')
|
||||
def _compute_amount_all(self):
|
||||
@@ -553,6 +575,8 @@ class PosOrder(models.Model):
|
||||
Move = self.env['stock.move']
|
||||
StockWarehouse = self.env['stock.warehouse']
|
||||
for order in self:
|
||||
if not order.lines.filtered(lambda l: l.product_id.type in ['product', 'consu']):
|
||||
continue
|
||||
address = order.partner_id.address_get(['delivery']) or {}
|
||||
picking_type = order.picking_type_id
|
||||
return_pick_type = order.picking_type_id.return_picking_type_id or order.picking_type_id
|
||||
@@ -582,7 +606,7 @@ class PosOrder(models.Model):
|
||||
'location_id': location_id,
|
||||
'location_dest_id': destination_id,
|
||||
}
|
||||
pos_qty = any([x.qty >= 0 for x in order.lines])
|
||||
pos_qty = any([x.qty > 0 for x in order.lines])
|
||||
if pos_qty:
|
||||
order_picking = Picking.create(picking_vals.copy())
|
||||
order_picking.message_post(body=message)
|
||||
@@ -620,8 +644,8 @@ class PosOrder(models.Model):
|
||||
|
||||
# when the pos.config has no picking_type_id set only the moves will be created
|
||||
if moves and not return_picking and not order_picking:
|
||||
moves.action_confirm()
|
||||
moves.force_assign()
|
||||
moves.action_assign()
|
||||
moves.filtered(lambda m: m.state in ['confirmed', 'waiting']).force_assign()
|
||||
moves.filtered(lambda m: m.product_id.tracking == 'none').action_done()
|
||||
|
||||
return True
|
||||
@@ -629,7 +653,7 @@ class PosOrder(models.Model):
|
||||
def _force_picking_done(self, picking):
|
||||
"""Force picking in order to be set as done."""
|
||||
self.ensure_one()
|
||||
picking.action_confirm()
|
||||
picking.action_assign()
|
||||
picking.force_assign()
|
||||
wrong_lots = self.set_pack_operation_lot(picking)
|
||||
if not wrong_lots:
|
||||
@@ -766,9 +790,9 @@ class PosOrderLine(models.Model):
|
||||
|
||||
def _order_line_fields(self, line, session_id=None):
|
||||
if line and 'name' not in line[2]:
|
||||
if session_id:
|
||||
session = self.env['pos.session'].browse(session_id).exists() if session_id else None
|
||||
if session and session.config_id.sequence_line_id:
|
||||
# set name based on the sequence specified on the config
|
||||
session = self.env['pos.session'].browse(session_id)
|
||||
line[2]['name'] = session.config_id.sequence_line_id._next()
|
||||
else:
|
||||
# fallback on any pos.order.line sequence
|
||||
|
||||
@@ -130,12 +130,20 @@ class PosSession(models.Model):
|
||||
@api.constrains('user_id', 'state')
|
||||
def _check_unicity(self):
|
||||
# open if there is no session in 'opening_control', 'opened', 'closing_control' for one user
|
||||
if self.search_count([('state', 'not in', ('closed', 'closing_control')), ('user_id', '=', self.user_id.id)]) > 1:
|
||||
if self.search_count([
|
||||
('state', 'not in', ('closed', 'closing_control')),
|
||||
('user_id', '=', self.user_id.id),
|
||||
('name', 'not like', 'RESCUE FOR'),
|
||||
]) > 1:
|
||||
raise ValidationError(_("You cannot create two active sessions with the same responsible!"))
|
||||
|
||||
@api.constrains('config_id')
|
||||
def _check_pos_config(self):
|
||||
if self.search_count([('state', '!=', 'closed'), ('config_id', '=', self.config_id.id)]) > 1:
|
||||
if self.search_count([
|
||||
('state', '!=', 'closed'),
|
||||
('config_id', '=', self.config_id.id),
|
||||
('name', 'not like', 'RESCUE FOR'),
|
||||
]) > 1:
|
||||
raise ValidationError(_("You cannot create two active sessions related to the same point of sale!"))
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -12,7 +12,7 @@ class PosOrderReport(models.Model):
|
||||
|
||||
date = fields.Datetime(string='Date Order', readonly=True)
|
||||
order_id = fields.Many2one('pos.order', string='Order', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Partner', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Customer', readonly=True)
|
||||
product_id = fields.Many2one('product.product', string='Product', readonly=True)
|
||||
product_tmpl_id = fields.Many2one('product.template', string='Product Template', readonly=True)
|
||||
state = fields.Selection(
|
||||
|
||||
@@ -11,6 +11,7 @@ var CrashManager = require('web.CrashManager');
|
||||
|
||||
|
||||
var _t = core._t;
|
||||
var _lt = core._lt;
|
||||
var QWeb = core.qweb;
|
||||
|
||||
/* -------- The Order Selector -------- */
|
||||
@@ -821,7 +822,7 @@ var Chrome = PosBaseWidget.extend({
|
||||
'widget': HeaderButtonWidget,
|
||||
'append': '.pos-rightheader',
|
||||
'args': {
|
||||
label: _t('Close'),
|
||||
label: _lt('Close'),
|
||||
action: function(){
|
||||
var self = this;
|
||||
if (!this.confirmed) {
|
||||
|
||||
@@ -1437,7 +1437,9 @@ exports.Orderline = Backbone.Model.extend({
|
||||
this.trigger('change',this);
|
||||
},
|
||||
get_unit_price: function(){
|
||||
return round_di(this.price || 0, this.pos.dp['Product Price'])
|
||||
var digits = this.pos.dp['Product Price'];
|
||||
// round and truncate to mimic _sybmbol_set behavior
|
||||
return parseFloat(round_di(this.price || 0, digits).toFixed(digits));
|
||||
},
|
||||
get_unit_display_price: function(){
|
||||
if (this.pos.config.iface_tax_included) {
|
||||
|
||||
@@ -1360,6 +1360,16 @@ var ClientListScreenWidget = ScreenWidget.extend({
|
||||
contents.append($(QWeb.render('ClientDetailsEdit',{widget:this,partner:partner})));
|
||||
this.toggle_save_button();
|
||||
|
||||
// Browsers attempt to scroll invisible input elements
|
||||
// into view (eg. when hidden behind keyboard). They don't
|
||||
// seem to take into account that some elements are not
|
||||
// scrollable.
|
||||
contents.find('input').blur(function() {
|
||||
setTimeout(function() {
|
||||
self.$('.window').scrollTop(0);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
contents.find('.image-uploader').on('change',function(event){
|
||||
self.load_image_file(event.target.files[0],function(res){
|
||||
if (res) {
|
||||
@@ -1409,7 +1419,9 @@ var ReceiptScreenWidget = ScreenWidget.extend({
|
||||
|
||||
this.render_change();
|
||||
this.render_receipt();
|
||||
|
||||
this.handle_auto_print();
|
||||
},
|
||||
handle_auto_print: function() {
|
||||
if (this.should_auto_print()) {
|
||||
this.print();
|
||||
if (this.should_close_immediately()){
|
||||
@@ -1418,7 +1430,6 @@ var ReceiptScreenWidget = ScreenWidget.extend({
|
||||
} else {
|
||||
this.lock_screen(false);
|
||||
}
|
||||
|
||||
},
|
||||
should_auto_print: function() {
|
||||
return this.pos.config.iface_print_auto && !this.pos.get_order()._printed;
|
||||
|
||||
@@ -10,12 +10,16 @@ class TestPointOfSaleCommon(common.TransactionCase):
|
||||
self.AccountBankStatementLine = self.env['account.bank.statement.line']
|
||||
self.PosMakePayment = self.env['pos.make.payment']
|
||||
self.PosOrder = self.env['pos.order']
|
||||
self.PosSession = self.env['pos.session']
|
||||
self.company_id = self.ref('base.main_company')
|
||||
self.product3 = self.env.ref('product.product_product_3')
|
||||
self.product4 = self.env.ref('product.product_product_4')
|
||||
self.partner1 = self.env.ref('base.res_partner_1')
|
||||
self.partner4 = self.env.ref('base.res_partner_4')
|
||||
self.pos_config = self.env.ref('point_of_sale.pos_config_main')
|
||||
self.carotte = self.env.ref('point_of_sale.carotte')
|
||||
self.courgette = self.env.ref('point_of_sale.courgette')
|
||||
self.onions = self.env.ref('point_of_sale.Onions')
|
||||
|
||||
# create a new session
|
||||
self.pos_order_session0 = self.env['pos.session'].create({
|
||||
|
||||
@@ -4,8 +4,8 @@ import time
|
||||
import os
|
||||
|
||||
import odoo
|
||||
from odoo import tools, report as odoo_report
|
||||
from odoo.tools import float_compare, test_reports
|
||||
from odoo import fields, tools, report as odoo_report
|
||||
from odoo.tools import float_compare, mute_logger, test_reports
|
||||
|
||||
from odoo.addons.point_of_sale.tests.common import TestPointOfSaleCommon
|
||||
|
||||
@@ -451,3 +451,138 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
|
||||
# I confirm the bank statement using Confirm button
|
||||
|
||||
self.AccountBankStatement.button_confirm_bank()
|
||||
|
||||
def test_create_from_ui(self):
|
||||
"""
|
||||
Simulation of sales coming from the interface, even after closing the session
|
||||
"""
|
||||
# I click on create a new session button
|
||||
self.pos_config.open_session_cb()
|
||||
|
||||
current_session = self.pos_config.current_session_id
|
||||
num_starting_orders = len(current_session.order_ids)
|
||||
|
||||
carrot_order = {'data':
|
||||
{'amount_paid': 0.9,
|
||||
'amount_return': 0,
|
||||
'amount_tax': 0,
|
||||
'amount_total': 0.9,
|
||||
'creation_date': fields.Datetime.now(),
|
||||
'fiscal_position_id': False,
|
||||
'lines': [[0,
|
||||
0,
|
||||
{'discount': 0,
|
||||
'id': 42,
|
||||
'pack_lot_ids': [],
|
||||
'price_unit': 0.9,
|
||||
'product_id': self.carotte.id,
|
||||
'qty': 1,
|
||||
'tax_ids': []}]],
|
||||
'name': 'Order 00042-003-0014',
|
||||
'partner_id': False,
|
||||
'pos_session_id': current_session.id,
|
||||
'sequence_number': 2,
|
||||
'statement_ids': [[0,
|
||||
0,
|
||||
{'account_id': self.env.user.partner_id.property_account_receivable_id.id,
|
||||
'amount': 0.9,
|
||||
'journal_id': self.pos_config.journal_ids[0].id,
|
||||
'name': fields.Datetime.now(),
|
||||
'statement_id': current_session.statement_ids[0].id}]],
|
||||
'uid': '00042-003-0014',
|
||||
'user_id': self.env.uid},
|
||||
'id': '00042-003-0014',
|
||||
'to_invoice': False}
|
||||
|
||||
zucchini_order = {'data':
|
||||
{'amount_paid': 1.2,
|
||||
'amount_return': 0,
|
||||
'amount_tax': 0,
|
||||
'amount_total': 1.1,
|
||||
'creation_date': fields.Datetime.now(),
|
||||
'fiscal_position_id': False,
|
||||
'lines': [[0,
|
||||
0,
|
||||
{'discount': 0,
|
||||
'id': 3,
|
||||
'pack_lot_ids': [],
|
||||
'price_unit': 1.2,
|
||||
'product_id': self.courgette.id,
|
||||
'qty': 1,
|
||||
'tax_ids': []}]],
|
||||
'name': 'Order 00043-003-0014',
|
||||
'partner_id': False,
|
||||
'pos_session_id': current_session.id,
|
||||
'sequence_number': self.pos_config.journal_id.id,
|
||||
'statement_ids': [[0,
|
||||
0,
|
||||
{'account_id': self.env.user.partner_id.property_account_receivable_id.id,
|
||||
'amount': 1.2,
|
||||
'journal_id': self.pos_config.journal_ids[0].id,
|
||||
'name': fields.Datetime.now(),
|
||||
'statement_id': current_session.statement_ids[0].id}]],
|
||||
'uid': '00043-003-0014',
|
||||
'user_id': self.env.uid},
|
||||
'id': '00043-003-0014',
|
||||
'to_invoice': False}
|
||||
|
||||
onions_order = {'data':
|
||||
{'amount_paid': 1.28,
|
||||
'amount_return': 0,
|
||||
'amount_tax': 0,
|
||||
'amount_total': 1.28,
|
||||
'creation_date': fields.Datetime.now(),
|
||||
'fiscal_position_id': False,
|
||||
'lines': [[0,
|
||||
0,
|
||||
{'discount': 0,
|
||||
'id': 3,
|
||||
'pack_lot_ids': [],
|
||||
'price_unit': 1.28,
|
||||
'product_id': self.onions.id,
|
||||
'qty': 1,
|
||||
'tax_ids': [[6, False, self.onions.taxes_id.ids]]}]],
|
||||
'name': 'Order 00044-003-0014',
|
||||
'partner_id': False,
|
||||
'pos_session_id': current_session.id,
|
||||
'sequence_number': self.pos_config.journal_id.id,
|
||||
'statement_ids': [[0,
|
||||
0,
|
||||
{'account_id': self.env.user.partner_id.property_account_receivable_id.id,
|
||||
'amount': 1.28,
|
||||
'journal_id': self.pos_config.journal_ids[0].id,
|
||||
'name': fields.Datetime.now(),
|
||||
'statement_id': current_session.statement_ids[0].id}]],
|
||||
'uid': '00044-003-0014',
|
||||
'user_id': self.env.uid},
|
||||
'id': '00044-003-0014',
|
||||
'to_invoice': False}
|
||||
|
||||
|
||||
# I create an order on an open session
|
||||
self.PosOrder.create_from_ui([carrot_order])
|
||||
self.assertEqual(num_starting_orders + 1, len(current_session.order_ids), "Submitted order not encoded")
|
||||
|
||||
# I resubmit the same order
|
||||
self.PosOrder.create_from_ui([carrot_order])
|
||||
self.assertEqual(num_starting_orders + 1, len(current_session.order_ids), "Resubmitted order was not skipped")
|
||||
|
||||
# I close the session
|
||||
current_session.action_pos_session_closing_control()
|
||||
self.assertEqual(current_session.state, 'closed', "Session was not properly closed")
|
||||
self.assertFalse(self.pos_config.current_session_id, "Current session not properly recomputed")
|
||||
|
||||
# I keep selling after the session is closed
|
||||
with mute_logger('odoo.addons.point_of_sale.models.pos_order'):
|
||||
self.PosOrder.create_from_ui([zucchini_order, onions_order])
|
||||
rescue_session = self.PosSession.search([
|
||||
('config_id', '=', self.pos_config.id),
|
||||
('state', '=', 'opened'),
|
||||
])
|
||||
self.assertEqual(len(rescue_session), 1, "One (and only one) rescue session should be created for orphan orders")
|
||||
self.assertIn("(RESCUE FOR %s)" % current_session.name, rescue_session.name, "Rescue session is not linked to the previous one")
|
||||
self.assertEqual(len(rescue_session.order_ids), 2, "Rescue session does not contain both orders")
|
||||
|
||||
# I close the rescue session
|
||||
rescue_session.action_pos_session_closing_control()
|
||||
self.assertEqual(rescue_session.state, 'closed', "Rescue session was not properly closed")
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
<field name="user_id" />
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="User" domain="[]" context="{'group_by' : 'user_id'}" />
|
||||
<filter string="Point of Sale" domain="[]" context="{'group_by': 'user_id'}" />
|
||||
<filter string="Point of Sale" domain="[]" context="{'group_by': 'config_id'}" />
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
||||
@@ -270,7 +270,7 @@ class Project(models.Model):
|
||||
def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True):
|
||||
""" Subscribe to all existing active tasks when subscribing to a project """
|
||||
res = super(Project, self).message_subscribe(partner_ids=partner_ids, channel_ids=channel_ids, subtype_ids=subtype_ids, force=force)
|
||||
if not subtype_ids or any(subtype.parent_id.model == 'project.task' for subtype in self.env['mail.message.subtype'].browse(subtype_ids)):
|
||||
if not subtype_ids or any(subtype.parent_id.res_model == 'project.task' for subtype in self.env['mail.message.subtype'].browse(subtype_ids)):
|
||||
for partner_id in partner_ids or []:
|
||||
self.mapped('tasks').filtered(lambda task: not task.stage_id.fold and partner_id not in task.message_partner_ids.ids).message_subscribe(
|
||||
partner_ids=[partner_id], channel_ids=None, subtype_ids=None, force=False)
|
||||
|
||||
@@ -553,13 +553,34 @@ class PurchaseOrderLine(models.Model):
|
||||
line = super(PurchaseOrderLine, self).create(values)
|
||||
if line.order_id.state == 'purchase':
|
||||
line.order_id._create_picking()
|
||||
msg = _("Extra line with %s ") % (line.product_id.display_name,)
|
||||
line.order_id.message_post(body=msg)
|
||||
return line
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
orders = False
|
||||
if 'product_qty' in values:
|
||||
changed_lines = self.filtered(lambda x: x.order_id.state == 'purchase')
|
||||
if changed_lines:
|
||||
orders = changed_lines.mapped('order_id')
|
||||
for order in orders:
|
||||
order_lines = changed_lines.filtered(lambda x: x.order_id == order)
|
||||
msg = ""
|
||||
if any([values['product_qty'] < x.product_qty for x in order_lines]):
|
||||
msg += "<b>" + _('The ordered quantity has been decreased. Do not forget to take it into account on your bills and receipts.') + '</b><br/>'
|
||||
msg += "<ul>"
|
||||
for line in order_lines:
|
||||
msg += "<li> %s:" % (line.product_id.display_name,)
|
||||
msg += "<br/>" + _("Ordered Quantity") + ": %s -> %s <br/>" % (line.product_qty, float(values['product_qty']),)
|
||||
if line.product_id.type in ('product', 'consu'):
|
||||
msg += _("Received Quantity") + ": %s <br/>" % (line.qty_received,)
|
||||
msg += _("Billed Quantity") + ": %s <br/></li>" % (line.qty_invoiced,)
|
||||
msg += "</ul>"
|
||||
order.message_post(body=msg)
|
||||
result = super(PurchaseOrderLine, self).write(values)
|
||||
orders = self.filtered(lambda x: x.order_id.state == 'purchase').mapped('order_id')
|
||||
orders._create_picking()
|
||||
if orders:
|
||||
orders._create_picking()
|
||||
return result
|
||||
|
||||
name = fields.Text(string='Description', required=True)
|
||||
@@ -959,6 +980,12 @@ class ProcurementOrder(models.Model):
|
||||
'group_id': group
|
||||
}
|
||||
|
||||
def _make_po_select_supplier(self, suppliers):
|
||||
""" Method intended to be overridden by customized modules to implement any logic in the
|
||||
selection of supplier.
|
||||
"""
|
||||
return suppliers[0]
|
||||
|
||||
@api.multi
|
||||
def make_po(self):
|
||||
cache = {}
|
||||
@@ -968,7 +995,7 @@ class ProcurementOrder(models.Model):
|
||||
if not suppliers:
|
||||
procurement.message_post(body=_('No vendor associated to product %s. Please set one to fix this procurement.') % (procurement.product_id.name))
|
||||
continue
|
||||
supplier = suppliers[0]
|
||||
supplier = procurement._make_po_select_supplier(suppliers)
|
||||
partner = supplier.name
|
||||
|
||||
gpo = procurement.rule_id.group_propagation_option
|
||||
|
||||
@@ -481,8 +481,11 @@ class Report(models.Model):
|
||||
out, err = process.communicate()
|
||||
|
||||
if process.returncode not in [0, 1]:
|
||||
raise UserError(_('Wkhtmltopdf failed (error code: %s). '
|
||||
'Message: %s') % (str(process.returncode), err))
|
||||
if process.returncode == -11:
|
||||
message = _('Wkhtmltopdf failed (error code: %s). Memory limit too low or maximum file number of subprocess reached. Message : %s')
|
||||
else:
|
||||
message = _('Wkhtmltopdf failed (error code: %s). Message: %s')
|
||||
raise UserError(message % (str(process.returncode), err[-1000:]))
|
||||
|
||||
# Save the pdf in attachment if marked
|
||||
if reporthtml[0] is not False:
|
||||
|
||||
@@ -6,7 +6,7 @@ from odoo import api, fields, models
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
paperformat_id = fields.Many2one('report.paperformat', 'Paper format')
|
||||
paperformat_id = fields.Many2one('report.paperformat', 'Paper format', default=lambda self: self.env.ref('report.paperformat_euro', raise_if_not_found=False))
|
||||
external_report_layout = fields.Selection([
|
||||
('background', 'Background'),
|
||||
('boxed', 'Boxed'),
|
||||
|
||||
@@ -84,6 +84,10 @@ class AccountInvoice(models.Model):
|
||||
|
||||
return report_pages
|
||||
|
||||
@api.multi
|
||||
def get_delivery_partner_id(self):
|
||||
self.ensure_one()
|
||||
return self.partner_shipping_id.id or super(AccountInvoice, self).get_delivery_partner_id()
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = 'account.invoice.line'
|
||||
|
||||
@@ -61,7 +61,9 @@ class SaleOrder(models.Model):
|
||||
for inv in invoice_ids:
|
||||
refund_ids += refund_ids.search([('type', '=', 'out_refund'), ('origin', '=', inv.number), ('origin', '!=', False), ('journal_id', '=', inv.journal_id.id)])
|
||||
|
||||
line_invoice_status = [line.invoice_status for line in order.order_line]
|
||||
# Ignore the status of the deposit product
|
||||
deposit_product_id = self.env['sale.advance.payment.inv']._default_product_id()
|
||||
line_invoice_status = [line.invoice_status for line in order.order_line if line.product_id != deposit_product_id]
|
||||
|
||||
if order.state not in ('sale', 'done'):
|
||||
invoice_status = 'no'
|
||||
@@ -511,11 +513,11 @@ class SaleOrder(models.Model):
|
||||
group = tax.tax_group_id
|
||||
res.setdefault(group, 0.0)
|
||||
amount = tax.compute_all(line.price_reduce + base_tax, quantity=line.product_uom_qty,
|
||||
product=line.product_id, partner=line.order_partner_id)['taxes'][0]['amount']
|
||||
product=line.product_id, partner=self.partner_shipping_id)['taxes'][0]['amount']
|
||||
res[group] += amount
|
||||
if tax.include_base_amount:
|
||||
base_tax += tax.compute_all(line.price_reduce + base_tax, quantity=1, product=line.product_id,
|
||||
partner=line.order_partner_id)['taxes'][0]['amount']
|
||||
partner=self.partner_shipping_id)['taxes'][0]['amount']
|
||||
res = sorted(res.items(), key=lambda l: l[0].sequence)
|
||||
res = map(lambda l: (l[0].name, l[1]), res)
|
||||
return res
|
||||
@@ -562,7 +564,7 @@ class SaleOrderLine(models.Model):
|
||||
"""
|
||||
for line in self:
|
||||
price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
|
||||
taxes = line.tax_id.compute_all(price, line.order_id.currency_id, line.product_uom_qty, product=line.product_id, partner=line.order_id.partner_id)
|
||||
taxes = line.tax_id.compute_all(price, line.order_id.currency_id, line.product_uom_qty, product=line.product_id, partner=line.order_id.partner_shipping_id)
|
||||
line.update({
|
||||
'price_tax': sum(t.get('amount', 0.0) for t in taxes.get('taxes', [])),
|
||||
'price_total': taxes['total_included'],
|
||||
@@ -628,7 +630,7 @@ class SaleOrderLine(models.Model):
|
||||
fpos = line.order_id.fiscal_position_id or line.order_id.partner_id.property_account_position_id
|
||||
# If company_id is set, always filter taxes by the company
|
||||
taxes = line.product_id.taxes_id.filtered(lambda r: not line.company_id or r.company_id == line.company_id)
|
||||
line.tax_id = fpos.map_tax(taxes, line.product_id, line.order_id.partner_id) if fpos else taxes
|
||||
line.tax_id = fpos.map_tax(taxes, line.product_id, line.order_id.partner_shipping_id) if fpos else taxes
|
||||
|
||||
@api.multi
|
||||
def _prepare_order_line_procurement(self, group_id=False):
|
||||
@@ -692,16 +694,37 @@ class SaleOrderLine(models.Model):
|
||||
line = super(SaleOrderLine, self).create(values)
|
||||
if line.state == 'sale':
|
||||
line._action_procurement_create()
|
||||
msg = _("Extra line with %s ") % (line.product_id.display_name,)
|
||||
line.order_id.message_post(body=msg)
|
||||
|
||||
return line
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
lines = False
|
||||
changed_lines = False
|
||||
if 'product_uom_qty' in values:
|
||||
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
lines = self.filtered(
|
||||
lambda r: r.state == 'sale' and float_compare(r.product_uom_qty, values['product_uom_qty'], precision_digits=precision) == -1)
|
||||
changed_lines = self.filtered(
|
||||
lambda r: r.state == 'sale' and float_compare(r.product_uom_qty, values['product_uom_qty'], precision_digits=precision) != 0)
|
||||
if changed_lines:
|
||||
orders = self.mapped('order_id')
|
||||
for order in orders:
|
||||
order_lines = changed_lines.filtered(lambda x: x.order_id == order)
|
||||
msg = ""
|
||||
if any([values['product_uom_qty'] < x.product_uom_qty for x in order_lines]):
|
||||
msg += "<b>" + _('The ordered quantity has been decreased. Do not forget to take it into account on your invoices and delivery orders.') + '</b>'
|
||||
msg += "<ul>"
|
||||
for line in order_lines:
|
||||
msg += "<li> %s:" % (line.product_id.display_name,)
|
||||
msg += "<br/>" + _("Ordered Quantity") + ": %s -> %s <br/>" % (line.product_uom_qty, float(values['product_uom_qty']),)
|
||||
if line.product_id.type in ('consu', 'product'):
|
||||
msg += _("Delivered Quantity") + ": %s <br/>" % (line.qty_delivered,)
|
||||
msg += _("Invoiced Quantity") + ": %s <br/>" % (line.qty_invoiced,)
|
||||
msg += "</ul>"
|
||||
order.message_post(body=msg)
|
||||
result = super(SaleOrderLine, self).write(values)
|
||||
if lines:
|
||||
lines._action_procurement_create()
|
||||
@@ -825,10 +848,16 @@ class SaleOrderLine(models.Model):
|
||||
@api.multi
|
||||
def _get_display_price(self, product):
|
||||
# TO DO: move me in master/saas-16 on sale.order
|
||||
if self.order_id.pricelist_id.discount_policy == 'without_discount':
|
||||
if self.order_id.pricelist_id.discount_policy == 'with_discount':
|
||||
return product.with_context(pricelist=self.order_id.pricelist_id.id).price
|
||||
price, rule_id = self.order_id.pricelist_id.get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id)
|
||||
pricelist_item = self.env['product.pricelist.item'].browse(rule_id)
|
||||
if (pricelist_item.base == 'pricelist' and pricelist_item.base_pricelist_id.discount_policy == 'with_discount'):
|
||||
price, rule_id = pricelist_item.base_pricelist_id.get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id)
|
||||
return price
|
||||
else:
|
||||
from_currency = self.order_id.company_id.currency_id
|
||||
return from_currency.compute(product.lst_price, self.order_id.pricelist_id.currency_id)
|
||||
return product.with_context(pricelist=self.order_id.pricelist_id.id).price
|
||||
|
||||
@api.multi
|
||||
@api.onchange('product_id')
|
||||
@@ -968,7 +997,7 @@ class SaleOrderLine(models.Model):
|
||||
new_list_price, currency_id = self.with_context(context_partner)._get_real_price_currency(self.product_id, rule_id, self.product_uom_qty, self.product_uom, self.order_id.pricelist_id.id)
|
||||
new_list_price = self.env['account.tax']._fix_tax_included_price(new_list_price, self.product_id.taxes_id, self.tax_id)
|
||||
|
||||
if price != 0 and new_list_price != 0:
|
||||
if new_list_price != 0:
|
||||
if self.product_id.company_id and self.order_id.pricelist_id.currency_id != self.product_id.company_id.currency_id:
|
||||
# new_list_price is in company's currency while price in pricelist currency
|
||||
new_list_price = self.env['res.currency'].browse(currency_id).with_context(context_partner).compute(new_list_price, self.order_id.pricelist_id.currency_id)
|
||||
|
||||
@@ -12,7 +12,19 @@ class SaleOrderLine(models.Model):
|
||||
lines = {}
|
||||
if not domain:
|
||||
# To filter on analyic lines linked to an expense
|
||||
domain = [('so_line', 'in', self.ids), ('amount', '<=', 0.0)]
|
||||
expense_type_id = self.env.ref('account.data_account_type_expenses', raise_if_not_found=False)
|
||||
expense_type_id = expense_type_id and expense_type_id.id
|
||||
domain = [
|
||||
('so_line', 'in', self.ids),
|
||||
'|',
|
||||
('amount', '<', 0),
|
||||
'&',
|
||||
('amount', '=', 0),
|
||||
'|',
|
||||
('move_id', '=', False),
|
||||
('move_id.account_id.user_type_id', '=', expense_type_id)
|
||||
]
|
||||
|
||||
data = self.env['account.analytic.line'].read_group(
|
||||
domain,
|
||||
['so_line', 'unit_amount', 'product_uom_id'], ['product_uom_id', 'so_line'], lazy=False
|
||||
|
||||
@@ -142,5 +142,18 @@ class SaleOrderLine(models.Model):
|
||||
def _compute_analytic(self, domain=None):
|
||||
if not domain:
|
||||
# To filter on analyic lines linked to an expense
|
||||
domain = [('so_line', 'in', self.ids), '|', ('amount', '<=', 0.0), ('project_id', '!=', False)]
|
||||
expense_type_id = self.env.ref('account.data_account_type_expenses', raise_if_not_found=False)
|
||||
expense_type_id = expense_type_id and expense_type_id.id
|
||||
domain = [
|
||||
('so_line', 'in', self.ids),
|
||||
'|',
|
||||
'|',
|
||||
('amount', '<', 0.0),
|
||||
('project_id', '!=', False),
|
||||
'&',
|
||||
('amount', '=', 0),
|
||||
'|',
|
||||
('move_id', '=', False),
|
||||
('move_id.account_id.user_type_id', '=', expense_type_id)
|
||||
]
|
||||
return super(SaleOrderLine, self)._compute_analytic(domain=domain)
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
<record id="team_sales_department" model="crm.team">
|
||||
<field name="name">Sales</field>
|
||||
<field name="member_ids" eval="[(4, ref('base.user_root'))]"/>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="salesteam_website_sales" model="crm.team">
|
||||
<field name="name">Website</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="team_type" eval="'website'"/>
|
||||
</record>
|
||||
|
||||
@@ -24,9 +24,11 @@ class CrmTeam(models.Model):
|
||||
def _get_default_team_id(self, user_id=None):
|
||||
if not user_id:
|
||||
user_id = self.env.uid
|
||||
team_id = self.env['crm.team'].sudo().search(
|
||||
['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)],
|
||||
limit=1)
|
||||
company_id = self.sudo(user_id).company_id.id
|
||||
team_id = self.env['crm.team'].sudo().search([
|
||||
'|', ('user_id', '=', user_id), ('member_ids', '=', user_id),
|
||||
'|', ('company_id', '=', False), ('company_id', 'child_of', [company_id])
|
||||
], limit=1)
|
||||
if not team_id and 'default_team_id' in self.env.context:
|
||||
team_id = self.env['crm.team'].browse(self.env.context.get('default_team_id'))
|
||||
if not team_id:
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
</a>
|
||||
</td>
|
||||
<td t-if="show_demo or (values and values['closing']['overdue'] != 0)" class="o_warning" title="To Opportunities">
|
||||
<a href="#" class="o_dashboard_action" name="crm.action_your_pipeline" data-context="{'search_default_overdue_opp':'1'}">
|
||||
<a href="#" class="o_dashboard_action" name="crm.crm_lead_action_activities" data-context="{'search_default_overdue_opp':'1'}">
|
||||
<t t-if="!show_demo">
|
||||
<t t-esc="values['closing']['overdue']"/> exp. closing
|
||||
</t>
|
||||
|
||||
@@ -275,23 +275,27 @@ class ProcurementOrder(models.Model):
|
||||
@api.model
|
||||
def _procure_orderpoint_confirm(self, use_new_cursor=False, company_id=False):
|
||||
""" Create procurements based on orderpoints.
|
||||
:param bool use_new_cursor: if set, use a dedicated cursor and auto-commit after processing each procurement.
|
||||
:param bool use_new_cursor: if set, use a dedicated cursor and auto-commit after processing
|
||||
1000 orderpoints.
|
||||
This is appropriate for batch jobs only.
|
||||
"""
|
||||
if use_new_cursor:
|
||||
cr = registry(self._cr.dbname).cursor()
|
||||
self = self.with_env(self.env(cr=cr))
|
||||
|
||||
OrderPoint = self.env['stock.warehouse.orderpoint']
|
||||
Procurement = self.env['procurement.order']
|
||||
ProcurementAutorundefer = Procurement.with_context(procurement_autorun_defer=True)
|
||||
procurement_list = []
|
||||
|
||||
orderpoints_noprefetch = OrderPoint.with_context(prefetch_fields=False).search(
|
||||
company_id and [('company_id', '=', company_id)] or [],
|
||||
order=self._procurement_from_orderpoint_get_order())
|
||||
domain = [('company_id', '=', company_id)] if company_id else []
|
||||
domain += [('product_id.active', '=', True)]
|
||||
orderpoints_noprefetch = OrderPoint.with_context(prefetch_fields=False).search(domain,
|
||||
order=self._procurement_from_orderpoint_get_order()).ids
|
||||
while orderpoints_noprefetch:
|
||||
orderpoints = OrderPoint.browse(orderpoints_noprefetch[:1000].ids)
|
||||
if use_new_cursor:
|
||||
cr = registry(self._cr.dbname).cursor()
|
||||
self = self.with_env(self.env(cr=cr))
|
||||
OrderPoint = self.env['stock.warehouse.orderpoint']
|
||||
Procurement = self.env['procurement.order']
|
||||
ProcurementAutorundefer = Procurement.with_context(procurement_autorun_defer=True)
|
||||
procurement_list = []
|
||||
|
||||
orderpoints = OrderPoint.browse(orderpoints_noprefetch[:1000])
|
||||
orderpoints_noprefetch = orderpoints_noprefetch[1000:]
|
||||
|
||||
# Calculate groups that can be executed together
|
||||
@@ -341,7 +345,7 @@ class ProcurementOrder(models.Model):
|
||||
|
||||
except OperationalError:
|
||||
if use_new_cursor:
|
||||
orderpoints_noprefetch += orderpoint.id
|
||||
orderpoints_noprefetch += [orderpoint.id]
|
||||
cr.rollback()
|
||||
continue
|
||||
else:
|
||||
@@ -365,8 +369,6 @@ class ProcurementOrder(models.Model):
|
||||
|
||||
if use_new_cursor:
|
||||
cr.commit()
|
||||
cr.close()
|
||||
|
||||
if use_new_cursor:
|
||||
cr.commit()
|
||||
cr.close()
|
||||
return {}
|
||||
|
||||
@@ -349,7 +349,7 @@ class StockMove(models.Model):
|
||||
raise UserError(_('Cannot unreserve a done move'))
|
||||
self.quants_unreserve()
|
||||
if not self.env.context.get('no_state_change'):
|
||||
waiting = self.filtered(lambda move: move.get_ancestors())
|
||||
waiting = self.filtered(lambda move: move.procure_method == 'make_to_order' or move.get_ancestors())
|
||||
waiting.write({'state': 'waiting'})
|
||||
(self - waiting).write({'state': 'confirmed'})
|
||||
|
||||
@@ -408,15 +408,8 @@ class StockMove(models.Model):
|
||||
type (moves should already have them identical). Otherwise, create a new
|
||||
picking to assign them to. """
|
||||
Picking = self.env['stock.picking']
|
||||
|
||||
# If this method is called in batch by a write on a one2many and
|
||||
# at some point had to create a picking, some next iterations could
|
||||
# try to find back the created picking. As we look for it by searching
|
||||
# on some computed fields, we have to force a recompute, else the
|
||||
# record won't be found.
|
||||
self.recompute()
|
||||
|
||||
for move in self:
|
||||
recompute = False
|
||||
picking = Picking.search([
|
||||
('group_id', '=', move.group_id.id),
|
||||
('location_id', '=', move.location_id.id),
|
||||
@@ -425,8 +418,17 @@ class StockMove(models.Model):
|
||||
('printed', '=', False),
|
||||
('state', 'in', ['draft', 'confirmed', 'waiting', 'partially_available', 'assigned'])], limit=1)
|
||||
if not picking:
|
||||
recompute = True
|
||||
picking = Picking.create(move._get_new_picking_values())
|
||||
move.write({'picking_id': picking.id})
|
||||
|
||||
# If this method is called in batch by a write on a one2many and
|
||||
# at some point had to create a picking, some next iterations could
|
||||
# try to find back the created picking. As we look for it by searching
|
||||
# on some computed fields, we have to force a recompute, else the
|
||||
# record won't be found.
|
||||
if recompute:
|
||||
move.recompute()
|
||||
return True
|
||||
_picking_assign = assign_picking
|
||||
|
||||
@@ -687,7 +689,7 @@ class StockMove(models.Model):
|
||||
if len(reserved_quant_ids) == 0 and move.partially_available:
|
||||
vals['partially_available'] = False
|
||||
if move.state == 'assigned':
|
||||
if move.find_move_ancestors():
|
||||
if move.procure_method == 'make_to_order' or move.find_move_ancestors():
|
||||
vals['state'] = 'waiting'
|
||||
else:
|
||||
vals['state'] = 'confirmed'
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<div t-field="o.partner_id"
|
||||
t-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": True}'/>
|
||||
</div>
|
||||
<div t-if="not (o.move_lines and o.move_lines[0].partner_id) and o.partner_id" name="partner_header">
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>
|
||||
|
||||
@@ -1726,4 +1726,69 @@ class TestStockFlow(TestStockCommon):
|
||||
|
||||
# force assign on the delivery order, it should be assigned
|
||||
picking_out.force_assign()
|
||||
self.assertEquals(picking_out.state, "assigned")
|
||||
self.assertEquals(picking_out.state, "assigned")
|
||||
|
||||
def test_74_move_state_waiting_mto(self):
|
||||
""" This test will check that when a move is unreserved, it state change to 'waiting' if
|
||||
it has ancestors or is has a 'procure_method' equal to 'make_to_order' else the state
|
||||
changes to 'confirmed'.
|
||||
"""
|
||||
picking_out = self.PickingObj.create({
|
||||
'partner_id': self.partner_agrolite_id,
|
||||
'picking_type_id': self.picking_type_out,
|
||||
'location_id': self.stock_location,
|
||||
'location_dest_id': self.customer_location})
|
||||
move_mto_alone = self.MoveObj.create({
|
||||
'name': self.productA.name,
|
||||
'product_id': self.productA.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.productA.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': self.stock_location,
|
||||
'location_dest_id': self.customer_location,
|
||||
'procure_method':'make_to_order'})
|
||||
move_with_ancestors = self.MoveObj.create({
|
||||
'name': self.productA.name,
|
||||
'product_id': self.productA.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.productA.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': self.stock_location,
|
||||
'location_dest_id': self.customer_location})
|
||||
the_ancestor = self.MoveObj.create({
|
||||
'name': self.productA.name,
|
||||
'product_id': self.productA.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.productA.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': self.stock_location,
|
||||
'location_dest_id': self.customer_location,
|
||||
'move_dest_id': move_with_ancestors.id})
|
||||
other_move = self.MoveObj.create({
|
||||
'name': self.productA.name,
|
||||
'product_id': self.productA.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.productA.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': self.stock_location,
|
||||
'location_dest_id': self.customer_location})
|
||||
|
||||
move_mto_alone.action_confirm()
|
||||
move_with_ancestors.action_confirm()
|
||||
other_move.action_confirm()
|
||||
|
||||
move_mto_alone.do_unreserve()
|
||||
move_with_ancestors.do_unreserve()
|
||||
other_move.do_unreserve()
|
||||
|
||||
self.assertEquals(move_mto_alone.state, "waiting")
|
||||
self.assertEquals(move_with_ancestors.state, "waiting")
|
||||
self.assertEquals(other_move.state, "confirmed")
|
||||
|
||||
move_mto_alone.recalculate_move_state()
|
||||
move_with_ancestors.recalculate_move_state()
|
||||
other_move.recalculate_move_state()
|
||||
|
||||
self.assertEquals(move_mto_alone.state, "waiting")
|
||||
self.assertEquals(move_with_ancestors.state, "waiting")
|
||||
self.assertEquals(other_move.state, "confirmed")
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
<field name="model">stock.warehouse</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Warehouse">
|
||||
<field name="name"/>
|
||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||
</search>
|
||||
</field>
|
||||
|
||||
@@ -188,7 +188,7 @@ class StockMove(models.Model):
|
||||
tmpl_dict = defaultdict(lambda: 0.0)
|
||||
# adapt standard price on incomming moves if the product cost_method is 'average'
|
||||
std_price_update = {}
|
||||
for move in self.filtered(lambda move: move.location_id.usage == 'supplier' and move.product_id.cost_method == 'average'):
|
||||
for move in self.filtered(lambda move: move.location_id.usage in ('supplier', 'production') and move.product_id.cost_method == 'average'):
|
||||
product_tot_qty_available = move.product_id.qty_available + tmpl_dict[move.product_id.id]
|
||||
|
||||
# if the incoming move is for a purchase order with foreign currency, need to call this to get the same value that the quant will use.
|
||||
|
||||
@@ -129,6 +129,7 @@ class LandedCost(models.Model):
|
||||
if quant.location_id.usage != 'internal':
|
||||
qty_out += quant.qty
|
||||
line._create_accounting_entries(move, qty_out)
|
||||
move.assert_balanced()
|
||||
cost.write({'state': 'done', 'account_move_id': move.id})
|
||||
move.post()
|
||||
return True
|
||||
@@ -326,7 +327,7 @@ class AdjustmentLines(models.Model):
|
||||
Generate the account.move.line values to track the landed cost.
|
||||
Afterwards, for the goods that are already out of stock, we should create the out moves
|
||||
"""
|
||||
AccountMoveLine = self.env['account.move.line'].with_context(check_move_validity=False)
|
||||
AccountMoveLine = self.env['account.move.line'].with_context(check_move_validity=False, recompute=False)
|
||||
|
||||
base_line = {
|
||||
'name': self.name,
|
||||
@@ -389,5 +390,4 @@ class AdjustmentLines(models.Model):
|
||||
AccountMoveLine.create(debit_line)
|
||||
AccountMoveLine.create(credit_line)
|
||||
|
||||
move.assert_balanced()
|
||||
return True
|
||||
|
||||
@@ -665,6 +665,8 @@ class Database(http.Controller):
|
||||
@http.route('/web/database/create', type='http', auth="none", methods=['POST'], csrf=False)
|
||||
def create(self, master_pwd, name, lang, password, **post):
|
||||
try:
|
||||
if not re.match('^[a-zA-Z][a-zA-Z0-9_]+$', name):
|
||||
raise Exception(_('Invalid database name. Only alphanumerical characters and underscore are allowed.'))
|
||||
# country code could be = "False" which is actually True in python
|
||||
country_code = post.get('country_code') or False
|
||||
dispatch_rpc('db', 'create_database', [master_pwd, name, bool(post.get('demo')), lang, password, post['login'], country_code])
|
||||
@@ -677,6 +679,8 @@ class Database(http.Controller):
|
||||
@http.route('/web/database/duplicate', type='http', auth="none", methods=['POST'], csrf=False)
|
||||
def duplicate(self, master_pwd, name, new_name):
|
||||
try:
|
||||
if not re.match('^[a-zA-Z][a-zA-Z0-9_]+$', new_name):
|
||||
raise Exception(_('Invalid database name. Only alphanumerical characters and underscore are allowed.'))
|
||||
dispatch_rpc('db', 'duplicate_database', [master_pwd, name, new_name])
|
||||
return http.local_redirect('/web/database/manager')
|
||||
except Exception as e:
|
||||
|
||||
@@ -25,6 +25,13 @@ var KanbanView = BasicView.extend({
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
var arch = viewInfo.arch;
|
||||
|
||||
this.loadParams.limit = this.loadParams.limit || 40;
|
||||
this.loadParams.openGroupByDefault = true;
|
||||
this.loadParams.type = 'list';
|
||||
|
||||
this.loadParams.groupBy = arch.attrs.default_group_by ? [arch.attrs.default_group_by] : (params.groupBy || []);
|
||||
|
||||
var activeActions = this.controllerParams.activeActions;
|
||||
activeActions = _.extend(activeActions, {
|
||||
group_edit: arch.attrs.group_edit ? JSON.parse(arch.attrs.group_edit) : true,
|
||||
@@ -35,7 +42,7 @@ var KanbanView = BasicView.extend({
|
||||
editable: activeActions.group_edit,
|
||||
deletable: activeActions.group_delete,
|
||||
group_creatable: true,
|
||||
quick_create: params.isQuickCreateEnabled || this._isQuickCreateEnabled(arch),
|
||||
quick_create: params.isQuickCreateEnabled || this._isQuickCreateEnabled(viewInfo),
|
||||
};
|
||||
this.rendererParams.record_options = {
|
||||
editable: activeActions.edit,
|
||||
@@ -47,19 +54,17 @@ var KanbanView = BasicView.extend({
|
||||
|
||||
this.controllerParams.readOnlyMode = false;
|
||||
this.controllerParams.hasButtons = true;
|
||||
|
||||
this.loadParams.limit = this.loadParams.limit || 40;
|
||||
this.loadParams.openGroupByDefault = true;
|
||||
this.loadParams.type = 'list';
|
||||
|
||||
this.loadParams.groupBy = arch.attrs.default_group_by ? [arch.attrs.default_group_by] : (params.groupBy || []);
|
||||
},
|
||||
_isQuickCreateEnabled: function (arch) {
|
||||
_isQuickCreateEnabled: function (viewInfo) {
|
||||
var groupBy = this.loadParams.groupBy[0];
|
||||
if(groupBy !== undefined && !_.contains(['char', 'boolean', 'many2one'], viewInfo.fields[groupBy].type)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.controllerParams.activeActions.create) {
|
||||
return false;
|
||||
}
|
||||
if (arch.attrs.quick_create !== undefined) {
|
||||
return JSON.parse(arch.attrs.quick_create);
|
||||
if (viewInfo.arch.attrs.quick_create !== undefined) {
|
||||
return JSON.parse(viewInfo.arch.attrs.quick_create);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -207,9 +207,15 @@ var DataExport = Dialog.extend({
|
||||
this.records = {};
|
||||
this.dataset = dataset;
|
||||
this.exports = new data.DataSetSearch(this, 'ir.exports', this.dataset.get_context());
|
||||
|
||||
|
||||
this.row_index = 0;
|
||||
this.row_index_level = 0;
|
||||
|
||||
// The default for the ".modal_content" element is "max-height: 100%;"
|
||||
// but we want it to always expand to "height: 100%;" for this modal.
|
||||
// This can be achieved thanks to LESS modification without touching
|
||||
// the ".modal-content" rules... but not with Internet explorer (11).
|
||||
this.$modal.find(".modal-content").css("height", "100%");
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
@@ -265,7 +271,7 @@ var DataExport = Dialog.extend({
|
||||
|
||||
function do_setup_export_formats(formats) {
|
||||
var $fmts = self.$('.o_export_format');
|
||||
|
||||
|
||||
_.each(formats, function(format, i) {
|
||||
var $radio = $('<input/>', {type: 'radio', value: format.tag, name: 'o_export_format_name'});
|
||||
var $label = $('<label/>', {html: format.label});
|
||||
@@ -374,7 +380,7 @@ var DataExport = Dialog.extend({
|
||||
},
|
||||
on_show_data: function(records, expansion) {
|
||||
var self = this;
|
||||
|
||||
|
||||
if(expansion) {
|
||||
this.$('.o_export_tree_item[data-id="' + expansion + '"]')
|
||||
.addClass('open')
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.o_web_client .o_export {
|
||||
|
||||
.o-flex(0, 1, 1000px);
|
||||
.o-flex(1, 1, auto);
|
||||
.o-flex-display();
|
||||
.o-flex-flow(column, nowrap);
|
||||
min-height: 0;
|
||||
|
||||
> p, > .row {
|
||||
.o-flex(0, 0, auto);
|
||||
@@ -28,8 +28,9 @@
|
||||
}
|
||||
|
||||
.o_export_panel {
|
||||
.o-flex(1, 0, 0);
|
||||
.o-flex(1, 1, auto);
|
||||
position: relative;
|
||||
min-height: 0;
|
||||
|
||||
> div {
|
||||
height: 100%;
|
||||
@@ -59,9 +60,10 @@
|
||||
.o_left_field_panel, .o_fields_list {
|
||||
border: 1px solid @odoo-brand-lightsecondary;
|
||||
overflow: auto;
|
||||
.o-flex(1, 0, 0);
|
||||
.o-flex(1, 1, auto);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
|
||||
.o_export_tree_item {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
@@ -72,7 +74,7 @@
|
||||
background-color: @odoo-brand-primary;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.o_expand_parent {
|
||||
.o-position-absolute(@top: 4px, @left: 5px);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<label for="name" class="control-label">Database Name</label>
|
||||
<input id="name" type="text" name="name" class="form-control" required="required" autocomplete="off"/>
|
||||
<input id="name" type="text" name="name" class="form-control" required="required" autocomplete="off" pattern="^[a-zA-Z][a-zA-Z0-9_]+$" title="Only alphanumerical characters and underscore are allowed"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -210,7 +210,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name" class="control-label">Database Name</label>
|
||||
<input id="name" type="text" name="name" class="form-control" required="required"/>
|
||||
<input id="name" type="text" name="name" class="form-control" required="required" pattern="^[a-zA-Z][a-zA-Z0-9_]+$" title="Only alphanumerical characters and underscore are allowed"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="copy">This database might have been moved or copied.</label>
|
||||
@@ -283,7 +283,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new_name" class="control-label">New Name</label>
|
||||
<input id="new_name" type="text" name="new_name" class="form-control" required="required"/>
|
||||
<input id="new_name" type="text" name="new_name" class="form-control" required="required" pattern="^[a-zA-Z][a-zA-Z0-9_]+$" title="Only alphanumerical characters and underscore are allowed"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
@@ -292,7 +292,15 @@ eventHandler.modules.popover.update = function ($popover, oStyle, isAirMode) {
|
||||
$imagePopover.find('.o_image_alt').text( (alt || "").replace(/"/g, '"') ).parent().toggle(oStyle.image.tagName === "IMG");
|
||||
$imagePopover.show();
|
||||
|
||||
range.createFromNode(dom.firstChild(oStyle.image)).select();
|
||||
// for video tag (non-void) we select the range over the tag,
|
||||
// for other media types we get the first descendant leaf element
|
||||
var target_node = oStyle.image;
|
||||
if (!oStyle.image.className.match(/(^|\s)media_iframe_video(\s|$)/i)) {
|
||||
target_node = dom.firstChild(target_node);
|
||||
}
|
||||
range.createFromNode(target_node).select();
|
||||
// save range on the editor so it is not lost if restored
|
||||
eventHandler.modules.editor.saveRange(dom.makeLayoutInfo(target_node).editable());
|
||||
} else {
|
||||
$(".note-control-selection").hide();
|
||||
}
|
||||
|
||||
@@ -636,9 +636,12 @@ var fontIconsDialog = Widget.extend({
|
||||
},
|
||||
renderElement: function () { // extract list of font (like awesome) from the cheatsheet.
|
||||
this.iconsParser = fontIcons;
|
||||
this.icons = _.flatten(_.map(fontIcons, function (data) {
|
||||
this.icons = _.flatten(_.map(fontIcons, function (data) { // TODO maybe useless now
|
||||
return data.icons;
|
||||
}));
|
||||
this.alias = _.flatten(_.map(fontIcons, function (data) {
|
||||
return data.alias;
|
||||
}));
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
search: function (needle) {
|
||||
@@ -740,11 +743,8 @@ var fontIconsDialog = Widget.extend({
|
||||
case '': continue;
|
||||
default:
|
||||
$(".font-icons-icon").removeClass("o_selected").filter("[data-alias*=',"+cls+",']").addClass("o_selected");
|
||||
for (var k=0; k<this.icons.length; k++) {
|
||||
if (this.icons.indexOf(cls) !== -1) {
|
||||
this.$('#fa-icon').val(cls);
|
||||
break;
|
||||
}
|
||||
if (this.alias.indexOf(cls) !== -1) {
|
||||
this.$('#fa-icon').val(cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,7 +300,8 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
this.update();
|
||||
}).bind(this));
|
||||
|
||||
window.location.href = session.debug ? $.param.querystring(tour.url, {debug: session.debug}) : tour.url;
|
||||
var url = session.debug ? $.param.querystring(tour.url, {debug: session.debug}) : tour.url;
|
||||
window.location.href = window.location.origin + url;
|
||||
} else {
|
||||
this.update();
|
||||
}
|
||||
|
||||
@@ -72,13 +72,19 @@ class WebsiteConfigSettings(models.TransientModel):
|
||||
config.language_count = len(self.language_ids)
|
||||
|
||||
def set_has_google_analytics(self):
|
||||
return self.env['ir.values'].set_default(
|
||||
if not self.user_has_groups('website.group_website_designer'):
|
||||
raise AccessDenied()
|
||||
return self.env['ir.values'].sudo().set_default(
|
||||
'website.config.settings', 'has_google_analytics', self.has_google_analytics)
|
||||
|
||||
def set_has_google_analytics_dashboard(self):
|
||||
return self.env['ir.values'].set_default(
|
||||
if not self.user_has_groups('website.group_website_designer'):
|
||||
raise AccessDenied()
|
||||
return self.env['ir.values'].sudo().set_default(
|
||||
'website.config.settings', 'has_google_analytics_dashboard', self.has_google_analytics_dashboard)
|
||||
|
||||
def set_has_google_maps(self):
|
||||
return self.env['ir.values'].set_default(
|
||||
if not self.user_has_groups('website.group_website_designer'):
|
||||
raise AccessDenied()
|
||||
return self.env['ir.values'].sudo().set_default(
|
||||
'website.config.settings', 'has_google_maps', self.has_google_maps)
|
||||
|
||||
@@ -339,6 +339,7 @@ var MenuEntryDialog = widget.LinkDialog.extend({
|
||||
|
||||
return {
|
||||
'TopBar': TopBarContent,
|
||||
'EditMenuDialog': EditMenuDialog,
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
<t t-set="title" t-value="main_object.website_meta_title"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-set="title"><t t-if="additional_title"><t t-raw="additional_title"/> | </t><t t-esc="(website or res_company).name"/></t>
|
||||
<t t-set="title"><t t-if="additional_title"><t t-raw="additional_title"/> | </t><t t-raw="(website or res_company).name"/></t>
|
||||
</t>
|
||||
</t>
|
||||
<t t-set="x_icon" t-value="'/web/image/website/%s/favicon/' % website.id"/>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="use_questions"/>
|
||||
<div class="row mt16" attrs="{'invisible': [('use_ticketing', '=', False)]}">
|
||||
<div class="row mt16" attrs="{'invisible': [('use_questions', '=', False)]}">
|
||||
<div class="col-md-9">
|
||||
<field name="question_ids"/>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,12 @@ class EventType(models.Model):
|
||||
website_track = fields.Boolean('Tracks on Website')
|
||||
website_track_proposal = fields.Boolean('Tracks Proposals on Website')
|
||||
|
||||
@api.onchange('website_menu')
|
||||
def _onchange_website_menu(self):
|
||||
if not self.website_menu:
|
||||
self.website_track = False
|
||||
self.website_track_proposal = False
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
_inherit = "event.event"
|
||||
@@ -64,10 +70,16 @@ class Event(models.Model):
|
||||
@api.onchange('event_type_id')
|
||||
def _onchange_type(self):
|
||||
super(Event, self)._onchange_type()
|
||||
if self.event_type_id:
|
||||
if self.event_type_id and self.website_menu:
|
||||
self.website_track = self.event_type_id.website_track
|
||||
self.website_track_proposal = self.event_type_id.website_track_proposal
|
||||
|
||||
@api.onchange('website_menu')
|
||||
def _onchange_website_menu(self):
|
||||
if not self.website_menu:
|
||||
self.website_track = False
|
||||
self.website_track_proposal = False
|
||||
|
||||
def _get_menu_entries(self):
|
||||
self.ensure_one()
|
||||
res = super(Event, self)._get_menu_entries()
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
<span t-if="not track.website_published" class="label label-warning">unpublished</span>
|
||||
</a>
|
||||
<div class="text-muted">
|
||||
<small t-esc="track.partner_id.sudo().name"/>
|
||||
<small t-if="track.partner_id" t-esc="track.partner_id.sudo().name"/>
|
||||
<small t-if="not track.partner_id" t-esc="track.partner_name"/>
|
||||
</div>
|
||||
</t>
|
||||
</td>
|
||||
@@ -98,7 +99,8 @@
|
||||
<span t-esc="track.name"/>
|
||||
</a>
|
||||
<div class="text-muted">
|
||||
<small t-esc="track.partner_id.sudo()"/>
|
||||
<small t-if="track.partner_id" t-esc="track.partner_id.sudo().name"/>
|
||||
<small t-if="not track.partner_id" t-esc="track.partner_name"/>
|
||||
</div>
|
||||
</td>
|
||||
</t>
|
||||
@@ -213,7 +215,10 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<h2 t-field="track.name"/>
|
||||
<small>Proposed by <span t-field="track.partner_name"/></small>
|
||||
<small>Proposed by
|
||||
<span t-if="track.partner_id" t-field="track.partner_id.sudo().name"/>
|
||||
<span t-if="not track.partner_id" t-field="track.partner_name"/>
|
||||
</small>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<p t-field="track.description"/>
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
<field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
</div>
|
||||
<field name="kanban_state" widget="kanban_state_selection"/>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<h1>
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
<field name="inherit_id" ref="website_event.event_type_view_form_inherit_website"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='event_type_visibility_website']/div[@class='o_setting_right_pane']" position='inside'>
|
||||
<div class="row mt16">
|
||||
<div class="row mt16" attrs="{'invisible': [('website_menu', '=', False)]}">
|
||||
<label class="col-md-4" for="website_track"/> <field name="website_track"/>
|
||||
</div>
|
||||
<div class="row mt16">
|
||||
<div class="row mt16" attrs="{'invisible': [('website_menu', '=', False)]}">
|
||||
<label class="col-md-4" for="website_track_proposal"/> <field name="website_track_proposal"/>
|
||||
</div>
|
||||
</xpath>
|
||||
|
||||
@@ -149,7 +149,7 @@ class PortalWizardUser(models.TransientModel):
|
||||
wizard_user.user_id.write({'active': True, 'groups_id': [(4, group_portal.id)]})
|
||||
# prepare for the signup process
|
||||
wizard_user.user_id.partner_id.signup_prepare()
|
||||
wizard_user._send_email()
|
||||
wizard_user.with_context(active_test=True)._send_email()
|
||||
wizard_user.refresh()
|
||||
else:
|
||||
# remove the user (if it exists) from the portal group
|
||||
|
||||
@@ -88,6 +88,14 @@ class SaleOrder(models.Model):
|
||||
super(SaleOrder, self).onchange_partner_id()
|
||||
self.note = self.template_id.note or self.note
|
||||
|
||||
@api.onchange('partner_id')
|
||||
def onchange_update_description_lang(self):
|
||||
if not self.template_id:
|
||||
return
|
||||
else:
|
||||
template = self.template_id.with_context(lang=self.partner_id.lang)
|
||||
self.website_description = template.website_description
|
||||
|
||||
@api.onchange('template_id')
|
||||
def onchange_template_id(self):
|
||||
if not self.template_id:
|
||||
|
||||
@@ -67,12 +67,11 @@ class SaleOrder(models.Model):
|
||||
'pricelist': order.pricelist_id.id,
|
||||
})
|
||||
product = self.env['product.product'].with_context(product_context).browse(product_id)
|
||||
|
||||
pu = product.price
|
||||
if order.pricelist_id and order.partner_id:
|
||||
order_line = order._cart_find_product_line(product.id)
|
||||
if order_line:
|
||||
pu = self.env['account.tax']._fix_tax_included_price(order_line._get_display_price(product), product.taxes_id, order_line.tax_id)
|
||||
pu = self.env['account.tax']._fix_tax_included_price(pu, product.taxes_id, order_line.tax_id)
|
||||
|
||||
return {
|
||||
'product_id': product_id,
|
||||
@@ -149,10 +148,19 @@ class SaleOrder(models.Model):
|
||||
else:
|
||||
# update line
|
||||
values = self._website_product_id_change(self.id, product_id, qty=quantity)
|
||||
|
||||
if self.pricelist_id.discount_policy == 'with_discount' and not self.env.context.get('fixed_price'):
|
||||
order = self.sudo().browse(self.id)
|
||||
product_context = dict(self.env.context)
|
||||
product_context.setdefault('lang', order.partner_id.lang)
|
||||
product_context.update({
|
||||
'partner': order.partner_id.id,
|
||||
'quantity': quantity,
|
||||
'date': order.date_order,
|
||||
'pricelist': order.pricelist_id.id,
|
||||
})
|
||||
product = self.env['product.product'].with_context(product_context).browse(product_id)
|
||||
values['price_unit'] = self.env['account.tax']._fix_tax_included_price(
|
||||
order_line._get_display_price(order_line.product_id),
|
||||
order_line._get_display_price(product),
|
||||
order_line.product_id.taxes_id,
|
||||
order_line.tax_id
|
||||
)
|
||||
|
||||
@@ -449,6 +449,10 @@ label.css_attribute_color.css_not_available {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.oe_website_sale input.quantity {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ---- Publish managment and options ---- */
|
||||
.oe_overlay_options .dropdown ul[name="size"] table {
|
||||
margin-left: 20px;
|
||||
|
||||
@@ -388,6 +388,9 @@ label.css_attribute_color.css_not_available
|
||||
min-width: 48px
|
||||
text-align: center
|
||||
|
||||
.oe_website_sale input.quantity
|
||||
padding: 0
|
||||
|
||||
/* ---- Publish managment and options ---- */
|
||||
|
||||
.oe_overlay_options
|
||||
|
||||
@@ -74,6 +74,7 @@ odoo.define('website_sale.website_sale', function (require) {
|
||||
var ajax = require('web.ajax');
|
||||
var utils = require('web.utils');
|
||||
var core = require('web.core');
|
||||
var config = require('web.config');
|
||||
var _t = core._t;
|
||||
|
||||
if(!$('.oe_website_sale').length) {
|
||||
@@ -295,8 +296,10 @@ odoo.define('website_sale.website_sale', function (require) {
|
||||
var $ul = $(ev.target).closest('.js_add_cart_variants');
|
||||
var $parent = $ul.closest('.js_product');
|
||||
var $product_id = $parent.find('input.product_id').first();
|
||||
var $price = $parent.find(".oe_price:first .oe_currency_value");
|
||||
var $default_price = $parent.find(".oe_default_price:first .oe_currency_value");
|
||||
var $price = $parent.find(".oe_price:first .oe_currency_value")
|
||||
.add($('#product_confirmation').find(".oe_price"));
|
||||
var $default_price = $parent.find(".oe_default_price:first .oe_currency_value")
|
||||
.add($('#product_confirmation').find(".oe_default_price:first .oe_currency_value"));
|
||||
var $optional_price = $parent.find(".oe_optional:first .oe_currency_value");
|
||||
var variant_ids = $ul.data("attribute_value_ids");
|
||||
var values = [];
|
||||
@@ -454,5 +457,8 @@ odoo.define('website_sale.website_sale', function (require) {
|
||||
$("select[name='country_id']").change();
|
||||
});
|
||||
|
||||
$('.ecom-zoomable img[data-zoom]').zoomOdoo({ attach: '#o-carousel-product'});
|
||||
// Deactivate image zoom for mobile devices, since it might prevent users to scroll
|
||||
if (config.device.size_class > config.device.SIZES.XS) {
|
||||
$('.ecom-zoomable img[data-zoom]').zoomOdoo({ attach: '#o-carousel-product'});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,6 +4,8 @@ odoo.define('website_sale.utils', function (require) {
|
||||
var animate_clone = function(cart, $elem, offset_top, offset_left) {
|
||||
cart.find('.o_animate_blink').addClass('o_red_highlight o_shadow_animation').delay(500).queue(function(){
|
||||
$(this).removeClass("o_shadow_animation").dequeue();
|
||||
}).delay(2000).queue(function(){
|
||||
$(this).removeClass("o_red_highlight").dequeue();
|
||||
});
|
||||
var imgtodrag = $elem.find('img').eq(0);
|
||||
if (imgtodrag.length) {
|
||||
|
||||
@@ -582,7 +582,7 @@
|
||||
<a t-attf-href="#" class="mb8 input-group-addon js_add_cart_json">
|
||||
<i class="fa fa-minus"></i>
|
||||
</a>
|
||||
<input type="text" class="form-control" data-min="1" name="add_qty" value="1"/>
|
||||
<input type="text" class="form-control quantity" data-min="1" name="add_qty" value="1"/>
|
||||
<a t-attf-href="#" class="mb8 input-group-addon float_left js_add_cart_json">
|
||||
<i class="fa fa-plus"></i>
|
||||
</a>
|
||||
@@ -613,10 +613,7 @@
|
||||
|
||||
<template id="product_variants" inherit_id="website_sale.product" active="False" customize_show="True" name="List View of Variants">
|
||||
<xpath expr="//t[@t-placeholder='select']" position="replace">
|
||||
<input type="hidden" t-if="len(product.product_variant_ids) == 1" name="product_id" t-att-value="product.product_variant_id.id"/>
|
||||
<t t-call="website_sale.variants">
|
||||
<t t-set="ul_class" t-value="'nav-stacked'"/>
|
||||
</t>
|
||||
<input type="hidden" t-if="len(product.product_variant_ids) == 1" class="product_id" name="product_id" t-att-value="product.product_variant_id.id"/>
|
||||
<t t-if="len(product.product_variant_ids) > 1">
|
||||
<label label-default="label-default" class="radio" t-foreach="product.product_variant_ids" t-as="variant_id">
|
||||
<input type="radio" name="product_id" class="js_product_change" t-att-checked="'checked' if variant_id_index == 0 else None" t-att-value="variant_id.id" t-att-data-lst_price="variant_id.lst_price" t-att-data-price="variant_id.price"/>
|
||||
@@ -890,7 +887,7 @@
|
||||
<a t-attf-href="#" class="mb8 input-group-addon js_add_cart_json hidden-xs">
|
||||
<i class="fa fa-minus"></i>
|
||||
</a>
|
||||
<input type="text" class="js_quantity form-control" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" t-att-value="int(line.product_uom_qty)" />
|
||||
<input type="text" class="js_quantity form-control quantity" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" t-att-value="int(line.product_uom_qty)" />
|
||||
<a t-attf-href="#" class="mb8 input-group-addon float_left js_add_cart_json hidden-xs">
|
||||
<i class="fa fa-plus"></i>
|
||||
</a>
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="add_to_compare" inherit_id="website_sale.products_item" active="True" customize_show="True" name="Comparison List">
|
||||
<template id="add_to_compare" inherit_id="website_sale.products_item" active="True" customize_show="True" name="Comparison List" priority="22">
|
||||
<xpath expr="//div[@class='product_price']" position="inside">
|
||||
<a class="hidden-xs btn btn-default btn-xs o_add_compare" title="Compare" t-att-data-product-product-id="product.product_variant_ids[0].id" data-action="o_comparelist"><span class="fa fa-exchange"></span></a>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="product_add_to_compare" name='Add to comparison in product page' inherit_id="website_sale.product">
|
||||
<template id="product_add_to_compare" name='Add to comparison in product page' inherit_id="website_sale.product" priority="8">
|
||||
<xpath expr="//a[@id='add_to_cart']" position="after">
|
||||
<t t-if="product.env.ref('website_sale_comparison.add_to_compare').active">
|
||||
<a class="hidden-xs btn btn-default btn-lg mt8 o_add_compare_dyn" title="Compare" t-att-data-product-product-id="product.product_variant_ids[0].id" data-action="o_comparelist"><span class="fa fa-exchange"></span></a>
|
||||
|
||||
@@ -58,14 +58,14 @@
|
||||
<a t-attf-href="#" class="mb8 input-group-addon js_add_cart_json hidden-xs">
|
||||
<i class="fa fa-minus"></i>
|
||||
</a>
|
||||
<input type="text" class="js_quantity form-control" data-min="1" name="add_qty" value="1"/>
|
||||
<input type="text" class="js_quantity form-control quantity" data-min="1" name="add_qty" value="1"/>
|
||||
<a t-attf-href="#" class="mb8 input-group-addon float_left js_add_cart_json hidden-xs">
|
||||
<i class="fa fa-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center td-price" name="price">
|
||||
<span t-attf-class="text-danger oe_default_price" t-att-style="'text-decoration: line-through; white-space: nowrap;' + '' if (compute_currency(product.lst_price) - product.with_context(quantity=1).website_price ) > 0.01 else 'display: none;'"
|
||||
<span t-attf-class="text-danger oe_default_price" style="text-decoration: line-through; white-space: nowrap;"
|
||||
t-field="product.lst_price"
|
||||
t-options='{
|
||||
"widget": "monetary",
|
||||
|
||||
@@ -33,3 +33,9 @@ class ProductWishlist(models.Model):
|
||||
'product_id': product_id,
|
||||
})
|
||||
return wish
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
wishlist_ids = fields.One2many('product.wishlist', 'partner_id', string='Wishlist', domain=[('active', '=', True)])
|
||||
|
||||
@@ -31,27 +31,40 @@ var ProductWishlist = Widget.extend({
|
||||
});
|
||||
|
||||
if ($('.wishlist-section').length) {
|
||||
$('.wishlist-section a.o_wish_rm').on('click', function (e){ self.wishlist_rm(e); });
|
||||
$('.wishlist-section a.o_wish_add').on('click', function (e){ self.wishlist_add(e); });
|
||||
$('.wishlist-section a.o_wish_mv').on('click', function (e){ self.wishlist_mv(e); });
|
||||
$('.wishlist-section a.o_wish_rm').on('click', function (e){ self.wishlist_rm(e, false); });
|
||||
$('.wishlist-section a.o_wish_add').on('click', function (e){ self.wishlist_add_or_mv(e); });
|
||||
}
|
||||
|
||||
$('.oe_website_sale').on('change', 'input.js_variant_change, select.js_variant_change, ul[data-attribute_value_ids]', function(ev) {
|
||||
var $ul = $(ev.target).closest('.js_add_cart_variants');
|
||||
var $parent = $ul.closest('.js_product');
|
||||
var $product_id = $parent.find('.product_id').first();
|
||||
var $el = $parent.find("[data-action='o_wishlist']");
|
||||
if (!_.contains(self.wishlist_product_ids, parseInt($product_id.val(), 10))) {
|
||||
$el.prop("disabled", false).removeClass('disabled').removeAttr('disabled');
|
||||
}
|
||||
else {
|
||||
$el.prop("disabled", true).addClass('disabled').attr('disabled', 'disabled');
|
||||
}
|
||||
});
|
||||
},
|
||||
add_new_products:function($el, e){
|
||||
var self = this;
|
||||
var product_id = $el.data('product-product-id');
|
||||
if (e.currentTarget.classList.contains('o_add_wishlist_dyn')) {
|
||||
product_id = parseInt($el.parent().find('.product_id').val());
|
||||
}
|
||||
if (odoo.session_info.is_website_user){
|
||||
this.warning_not_logged();
|
||||
} else {
|
||||
var product_id = $el.data('product-product-id');
|
||||
if (e.currentTarget.classList.contains('o_add_wishlist_dyn')) {
|
||||
product_id = parseInt($el.parent().find('.product_id').val());
|
||||
}
|
||||
if (!_.contains(self.wishlist_product_ids, product_id)) {
|
||||
return ajax.jsonRpc('/shop/wishlist/add', 'call', {
|
||||
'product_id': product_id
|
||||
}).then(function () {
|
||||
self.wishlist_product_ids.push(product_id);
|
||||
self.update_wishlist_view();
|
||||
website_sale_utils.animate_clone($('#my_wish'), $el.closest('form'), 10, 10);
|
||||
website_sale_utils.animate_clone($('#my_wish'), $el.closest('form'), 25, 40);
|
||||
$el.prop("disabled", true).addClass('disabled');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -77,10 +90,11 @@ var ProductWishlist = Widget.extend({
|
||||
$('#my_wish').hide();
|
||||
}
|
||||
},
|
||||
wishlist_rm: function(e){
|
||||
wishlist_rm: function(e, deferred_redirect){
|
||||
var tr = $(e.currentTarget).parents('tr');
|
||||
var wish = tr.data('wish-id');
|
||||
var product = tr.data('product-id');
|
||||
var self = this;
|
||||
|
||||
rpc.query({
|
||||
model: 'product.wishlist',
|
||||
@@ -90,19 +104,26 @@ var ProductWishlist = Widget.extend({
|
||||
.then(function(){
|
||||
$(tr).hide();
|
||||
});
|
||||
|
||||
this.wishlist_product_ids = _.without(this.wishlist_product_ids, product);
|
||||
if (this.wishlist_product_ids.length === 0) {
|
||||
this.redirect_no_wish();
|
||||
deferred_redirect = deferred_redirect ? deferred_redirect : $.Deferred();
|
||||
deferred_redirect.then(function() {
|
||||
self.redirect_no_wish();
|
||||
});
|
||||
}
|
||||
this.update_wishlist_view();
|
||||
},
|
||||
wishlist_add_or_mv: function(e){
|
||||
return $('#b2b_wish').is(':checked') ? this.wishlist_add(e) : this.wishlist_mv(e);
|
||||
},
|
||||
wishlist_add: function(e){
|
||||
var tr = $(e.currentTarget).parents('tr');
|
||||
var product = tr.data('product-id');
|
||||
|
||||
// can be hidden if empty
|
||||
$('#my_cart').removeClass('hidden');
|
||||
website_sale_utils.animate_clone($('#my_cart'), tr, 0, 0);
|
||||
website_sale_utils.animate_clone($('#my_cart'), tr, 25, 40);
|
||||
this.add_to_cart(product, tr.find('qty').val() || 1);
|
||||
},
|
||||
wishlist_mv: function(e){
|
||||
@@ -110,15 +131,20 @@ var ProductWishlist = Widget.extend({
|
||||
var product = tr.data('product-id');
|
||||
|
||||
$('#my_cart').removeClass('hidden');
|
||||
website_sale_utils.animate_clone($('#my_cart'), tr, 0, 0);
|
||||
this.add_to_cart(product, tr.find('qty').val() || 1);
|
||||
this.wishlist_rm(e);
|
||||
website_sale_utils.animate_clone($('#my_cart'), tr, 25, 40);
|
||||
var adding_deffered = this.add_to_cart(product, tr.find('qty').val() || 1);
|
||||
this.wishlist_rm(e, adding_deffered);
|
||||
},
|
||||
add_to_cart: function(product_id, qty_id) {
|
||||
ajax.jsonRpc("/shop/cart/update_json", 'call', {
|
||||
var add_to_cart = ajax.jsonRpc("/shop/cart/update_json", 'call', {
|
||||
'product_id': parseInt(product_id, 10),
|
||||
'add_qty': parseInt(qty_id, 10)
|
||||
});
|
||||
|
||||
add_to_cart.then(function(resp) {
|
||||
$('.my_cart_quantity').text(resp.cart_quantity || '* 1');
|
||||
});
|
||||
return add_to_cart;
|
||||
},
|
||||
redirect_no_wish: function() {
|
||||
window.location = '/shop/cart';
|
||||
|
||||
@@ -8,16 +8,18 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="add_to_wishlist" inherit_id="website_sale.products_item" active="True" customize_show="True" name="Wishlist" priority="10">
|
||||
<template id="add_to_wishlist" inherit_id="website_sale.products_item" active="True" customize_show="True" name="Wishlist" priority="20">
|
||||
<xpath expr="//div[@class='product_price']" position="inside">
|
||||
<a class="btn btn-default btn-xs o_add_wishlist" title="Add to Wishlist" t-att-data-product-product-id="product.product_variant_ids[0].id" data-action="o_wishlist"><span class="fa fa-heart"></span></a>
|
||||
<t t-set="in_wish" t-value="product.product_variant_ids[0] in request.env.user.partner_id.wishlist_ids.mapped('product_id')"/>
|
||||
<a class="btn btn-default btn-xs o_add_wishlist" t-att-disabled='in_wish or None' title="Add to Wishlist" t-att-data-product-product-id="product.product_variant_ids[0].id" data-action="o_wishlist"><span class="fa fa-heart"></span></a>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="product_add_to_wishlist" name='Add to wishlist in product page' inherit_id="website_sale.product" priority="10">
|
||||
<template id="product_add_to_wishlist" name='Add to wishlist in product page' inherit_id="website_sale.product" priority="20">
|
||||
<xpath expr="//a[@id='add_to_cart']" position="after">
|
||||
<t t-if="product.env.ref('website_sale_wishlist.add_to_wishlist').active">
|
||||
<a class="btn btn-default btn-lg mt8 o_add_wishlist_dyn" title="Add to Wishlist" t-att-data-product-product-id="product.product_variant_ids[0].id" data-action="o_wishlist"><span class="fa fa-heart"></span></a>
|
||||
<t t-set="in_wish" t-value="product.product_variant_ids[0] in request.env.user.partner_id.wishlist_ids.mapped('product_id')"/>
|
||||
<a class="btn btn-default btn-lg mt8 o_add_wishlist_dyn" t-att-disabled='in_wish or None' title="Add to Wishlist" t-att-data-product-product-id="product.product_variant_ids[0].id" data-action="o_wishlist"><span class="fa fa-heart"></span></a>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -44,6 +46,9 @@
|
||||
<div class="container oe_website_sale">
|
||||
<section class="container wishlist-section">
|
||||
<h3>My Wishlist</h3>
|
||||
<div class="checkbox">
|
||||
<label class='text-muted'><input type="checkbox" id='b2b_wish' value="1" />Add product to my cart but keep it in my wishlist</label>
|
||||
</div>
|
||||
<table class="table table-bordered table-striped table-hover text-center mt16 table-comparator" id="o_comparelist_table">
|
||||
<body>
|
||||
<t t-foreach="wishes" t-as="wish">
|
||||
@@ -75,7 +80,6 @@
|
||||
</td>
|
||||
<td class='text-center td-wish-btn'>
|
||||
<input name="product_id" t-att-value="wish.product_id.id" type="hidden"/>
|
||||
<a class="btn btn-primary btn-block o_wish_mv mb4">Move <span class='hidden-xs'>to Cart</span></a>
|
||||
<a class="btn btn-default btn-block o_wish_add mb4" >Add <span class='hidden-xs'>to Cart</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
Canada, 2017-3-24
|
||||
|
||||
Métal Sartigan 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,
|
||||
|
||||
Jérôme Thériault jerther@gmail.com https://github.com/jerther
|
||||
|
||||
List of contributors:
|
||||
|
||||
Jérôme Thériault jerther@gmail.com https://github.com/jerther
|
||||
@@ -0,0 +1,15 @@
|
||||
Spain, 2017-03-30
|
||||
|
||||
OnTruck 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,
|
||||
|
||||
Iñigo Juantegui
|
||||
|
||||
List of contributors:
|
||||
|
||||
Antonio Espinosa <antonio.espinosa@ontruck.com> https://github.com/antespi
|
||||
@@ -0,0 +1,22 @@
|
||||
Spain, 2017-04-04
|
||||
|
||||
Tecnativa S.L. 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,
|
||||
|
||||
Pedro M. Baeza pedro.baeza@tecnativa.com https://github.com/pedrobaeza
|
||||
|
||||
List of contributors:
|
||||
|
||||
Pedro M. Baeza pedro.baeza@tecnativa.com https://github.com/pedrobaeza
|
||||
Rafael Blasco rafael.blasco@tecnativa.com https://github.com/rafaelbn
|
||||
Sergio Teruel sergio.teruel@tecnativa.com https://github.com/sergio-teruel
|
||||
Carlos Dauden carlos.dauden@tecnativa.com https://github.com/carlosdauden
|
||||
Jairo Llopis jairo.llopis@tecnativa.com https://github.com/yajo
|
||||
Vicent Cubells vicent.cubells@tecnativa.com https://github.com/cubells
|
||||
Luis Montalba luis.montalba@tecnativa.com https://github.com/luismontalba
|
||||
David Vidal david.vidal@tecnativa.com https://github.com/chienandalu
|
||||
@@ -1,4 +1,4 @@
|
||||
Vietnam, 2016-11-30
|
||||
Vietnam, 2017-04-03
|
||||
|
||||
T.V.T Marine Automation agrees to the terms of the Odoo Corporate Contributor License
|
||||
Agreement v1.0.
|
||||
@@ -12,4 +12,6 @@ David Tran david.tran@tvtmarine.com https://github.com/tvtma/
|
||||
|
||||
List of contributors:
|
||||
|
||||
David Tran david.tran@tvtmarine.com https://github.com/tvtma/
|
||||
David Tran david.tran@tvtmarine.com https://github.com/davidtranhp
|
||||
Long Do dhlong.1209@gmail.com https://github.com/hoanglong87
|
||||
Hao Hoang hao.hoang@ma.tvtmarine.com https://github.com/hoanghao2001
|
||||
@@ -0,0 +1,9 @@
|
||||
Azer, 2017-03-26
|
||||
|
||||
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,
|
||||
|
||||
GHADHOUN AZER ezer1989@gmail.com https://github.com/monami7001
|
||||
@@ -0,0 +1,11 @@
|
||||
Vietnam, 2017-04-10
|
||||
|
||||
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,
|
||||
|
||||
Tran Thanh Phuc ttp.phuctran@gmail.com https://github.com/ttpphuctran
|
||||
+2
-2
@@ -14,7 +14,7 @@ requirement is explained in the [FAQ](#faq).
|
||||
`odony`, the file would be `doc/cla/individual/odony.md`. The file should
|
||||
contain:
|
||||
|
||||
```
|
||||
```
|
||||
<country>, <date>
|
||||
|
||||
I hereby agree to the terms of the Odoo Individual Contributor License
|
||||
@@ -50,7 +50,7 @@ signature is merged.
|
||||
If the name of the company is Odoo, the file would be
|
||||
`doc/cla/corporate/odoo.md`. The file should contain:
|
||||
|
||||
```
|
||||
```
|
||||
<country>, <date>
|
||||
|
||||
<company-name> agrees to the terms of the Odoo Corporate Contributor License
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user