summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorOlivier Dony <odo@openerp.com>2017-05-16 18:23:03 +0200
committerOlivier Dony <odo@openerp.com>2017-05-16 18:23:15 +0200
commit5f4db9df6640100302ab7967344e12ab877089cb (patch)
tree934f0ceb590fb72846c12cb046d96ff609554951 /addons
parentcbca7e13132fe807ac918d9b3c2fcbbb3a12a103 (diff)
parent5afe894f440eff3b58134d14fa7c9b43b19fe88b (diff)
[MERGE] Forward-port saas-16 up to 5afe894f440eff3b58134d14fa7c9b43b19fe88b
Diffstat (limited to 'addons')
-rw-r--r--addons/account/models/account_bank_statement.py11
-rw-r--r--addons/account/models/company.py9
-rw-r--r--addons/account/report/account_invoice_report.py2
-rw-r--r--addons/account/static/src/js/reconciliation/reconciliation_action.js13
-rw-r--r--addons/account/static/src/js/reconciliation/reconciliation_model.js18
-rw-r--r--addons/account/static/src/js/reconciliation/reconciliation_renderer.js4
-rw-r--r--addons/account/static/src/xml/account_reconciliation.xml2
-rw-r--r--addons/account/static/tests/reconciliation_tests.js33
-rw-r--r--addons/account/views/account_view.xml7
-rw-r--r--addons/auth_signup/controllers/main.py3
-rw-r--r--addons/auth_signup/models/res_users.py3
-rw-r--r--addons/barcodes/static/src/js/barcode_form_view.js55
-rw-r--r--addons/base_automation/views/base_automation_view.xml7
-rw-r--r--addons/fleet/models/fleet_vehicle.py2
-rw-r--r--addons/google_spreadsheet/views/base_config_settings_views.xml11
-rw-r--r--addons/hr/models/hr.py4
-rw-r--r--addons/hr/views/hr_views.xml4
-rw-r--r--addons/hr_contract/models/hr_contract.py21
-rw-r--r--addons/hr_contract/views/hr_contract_views.xml86
-rw-r--r--addons/hr_payroll/models/hr_contract.py5
-rw-r--r--addons/hr_payroll/security/ir.model.access.csv2
-rw-r--r--addons/hr_payroll/views/hr_contract_views.xml2
-rw-r--r--addons/hr_recruitment/models/hr_job.py3
-rw-r--r--addons/hr_recruitment/views/hr_recruitment_views.xml16
-rw-r--r--addons/hr_timesheet/models/hr_timesheet.py11
-rw-r--r--addons/hr_timesheet/tests/__init__.py4
-rw-r--r--addons/hr_timesheet/tests/test_timesheet.py118
-rw-r--r--addons/im_livechat/models/im_livechat_channel.py2
-rw-r--r--addons/im_livechat/views/im_livechat_channel_templates.xml9
-rw-r--r--addons/l10n_be_hr_payroll/data/hr.salary.rule.csv2842
-rw-r--r--addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml4
-rw-r--r--addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py58
-rw-r--r--addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml3
-rw-r--r--addons/l10n_be_hr_payroll_fleet/models/fleet.py22
-rw-r--r--addons/l10n_be_hr_payroll_fleet/models/hr_contract.py5
-rw-r--r--addons/l10n_be_hr_payroll_fleet/views/fleet_views.xml50
-rw-r--r--addons/l10n_be_hr_payroll_fleet/views/hr_contract_views.xml14
-rw-r--r--addons/l10n_fr/__manifest__.py1
-rw-r--r--addons/l10n_fr/data/account_tax_data.xml90
-rw-r--r--addons/l10n_fr_hr_payroll/report/report_l10n_fr_fiche_paye.xml2
-rw-r--r--addons/mail/static/src/js/composer.js7
-rw-r--r--addons/mail/static/tests/chatter_tests.js49
-rw-r--r--addons/mass_mailing/models/mass_mailing.py2
-rw-r--r--addons/mass_mailing/static/src/js/mass_mailing_editor.js20
-rw-r--r--addons/mass_mailing/static/src/less/themes/theme_default.less39
-rw-r--r--addons/mrp/models/mrp_production.py3
-rw-r--r--addons/mrp/static/tests/mrp_tests.js4
-rw-r--r--addons/pad/static/src/js/pad.js227
-rw-r--r--addons/pad/static/tests/pad_tests.js151
-rw-r--r--addons/pad/views/pad.xml6
-rw-r--r--addons/payment/models/payment_acquirer.py10
-rw-r--r--addons/point_of_sale/models/pos_order.py2
-rw-r--r--addons/point_of_sale/static/src/xml/pos.xml24
-rw-r--r--addons/pos_mercury/models/pos_mercury_transaction.py3
-rw-r--r--addons/pos_restaurant/static/src/js/floors.js7
-rw-r--r--addons/product/models/res_company.py5
-rw-r--r--addons/project_timesheet_holidays/models/hr_holidays.py1
-rw-r--r--addons/project_timesheet_holidays/tests/__init__.py4
-rw-r--r--addons/project_timesheet_holidays/tests/test_timesheet_holidays.py87
-rw-r--r--addons/sale/report/sale_report.xml10
-rw-r--r--addons/sale/report/sale_report_templates.xml4
-rw-r--r--addons/sale/security/sale_security.xml1
-rw-r--r--addons/sale/wizard/sale_make_invoice_advance.py14
-rw-r--r--addons/sale_mrp/sale_mrp.py24
-rw-r--r--addons/sale_timesheet/models/account.py15
-rw-r--r--addons/sale_timesheet/models/account_invoice.py8
-rw-r--r--addons/sale_timesheet/models/procurement.py2
-rw-r--r--addons/sale_timesheet/tests/__init__.py8
-rw-r--r--addons/sale_timesheet/tests/test_timesheet_revenue.py284
-rw-r--r--addons/sales_team/static/src/js/sales_team_dashboard.js26
-rw-r--r--addons/stock/models/procurement.py9
-rw-r--r--addons/stock/models/res_company.py7
-rw-r--r--addons/stock/models/stock_move.py5
-rw-r--r--addons/stock/views/stock_picking_views.xml2
-rw-r--r--addons/stock_account/models/stock.py6
-rw-r--r--addons/web/controllers/main.py6
-rw-r--r--addons/web/doc/guidelines.rst1
-rw-r--r--addons/web/static/lib/benchmarkjs/LICENSE22
-rw-r--r--addons/web/static/lib/benchmarkjs/benchmark.js2824
-rw-r--r--addons/web/static/lib/benchmarkjs/lodash.js17084
-rw-r--r--addons/web/static/src/js/fields/abstract_field.js74
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js125
-rw-r--r--addons/web/static/src/js/fields/field_utils.js14
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js82
-rw-r--r--addons/web/static/src/js/services/data_manager.js2
-rw-r--r--addons/web/static/src/js/views/abstract_renderer.js7
-rw-r--r--addons/web/static/src/js/views/abstract_view.js2
-rw-r--r--addons/web/static/src/js/views/basic/basic_controller.js65
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js209
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js26
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_quick_create.js52
-rw-r--r--addons/web/static/src/js/views/form/form_controller.js46
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js265
-rw-r--r--addons/web/static/src/js/views/graph/graph_controller.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_controller.js3
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_model.js7
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_record.js5
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_renderer.js4
-rw-r--r--addons/web/static/src/js/views/list/list_controller.js19
-rw-r--r--addons/web/static/src/js/views/list/list_editable_renderer.js313
-rw-r--r--addons/web/static/src/js/views/list/list_renderer.js12
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_renderer.js19
-rw-r--r--addons/web/static/src/js/views/view_dialogs.js3
-rw-r--r--addons/web/static/src/js/widgets/date_picker.js135
-rw-r--r--addons/web/static/src/js/widgets/debug_manager.js1
-rw-r--r--addons/web/static/src/js/widgets/domain_selector.js4
-rw-r--r--addons/web/static/src/less/fields.less35
-rw-r--r--addons/web/static/src/less/list_view.less7
-rw-r--r--addons/web/static/src/xml/base.xml4
-rw-r--r--addons/web/static/tests/fields/basic_fields_tests.js109
-rw-r--r--addons/web/static/tests/fields/field_utils_tests.js11
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js19
-rw-r--r--addons/web/static/tests/helpers/mock_server.js7
-rw-r--r--addons/web/static/tests/helpers/qunit_config.js17
-rw-r--r--addons/web/static/tests/helpers/test_utils.js26
-rw-r--r--addons/web/static/tests/views/basic_model_tests.js40
-rw-r--r--addons/web/static/tests/views/calendar_tests.js25
-rw-r--r--addons/web/static/tests/views/form_tests.js477
-rw-r--r--addons/web/static/tests/views/kanban_benchmarks.js83
-rw-r--r--addons/web/static/tests/views/kanban_tests.js112
-rw-r--r--addons/web/static/tests/views/list_benchmarks.js102
-rw-r--r--addons/web/static/tests/views/list_tests.js196
-rw-r--r--addons/web/static/tests/views/view_dialogs_tests.js5
-rw-r--r--addons/web/views/webclient_templates.xml56
-rw-r--r--addons/web_editor/static/src/js/ace.js37
-rw-r--r--addons/web_tour/static/src/less/tip.less24
-rw-r--r--addons/website/static/src/js/website.snippets.animation.js93
-rw-r--r--addons/website/static/src/js/website.snippets.editor.js3
-rw-r--r--addons/website/static/src/less/website.snippets.less7
-rw-r--r--addons/website_event/models/event.py19
-rw-r--r--addons/website_event_track/models/event.py15
-rw-r--r--addons/website_form/controllers/main.py2
-rw-r--r--addons/website_mail_channel/controllers/main.py11
-rw-r--r--addons/website_sale/views/templates.xml4
134 files changed, 24958 insertions, 2655 deletions
diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py
index 73a4102311e..5b486a5462d 100644
--- a/addons/account/models/account_bank_statement.py
+++ b/addons/account/models/account_bank_statement.py
@@ -93,6 +93,11 @@ class AccountBankStatement(models.Model):
def _check_lines_reconciled(self):
self.all_lines_reconciled = all([line.journal_entry_ids.ids or line.account_id.id for line in self.line_ids])
+ @api.depends('move_line_ids')
+ def _get_move_line_count(self):
+ for payment in self:
+ payment.move_line_count = len(payment.move_line_ids)
+
@api.model
def _default_journal(self):
journal_type = self.env.context.get('journal_type', False)
@@ -146,6 +151,8 @@ class AccountBankStatement(models.Model):
line_ids = fields.One2many('account.bank.statement.line', 'statement_id', string='Statement lines', states={'confirm': [('readonly', True)]}, copy=True)
move_line_ids = fields.One2many('account.move.line', 'statement_id', string='Entry lines', states={'confirm': [('readonly', True)]})
+ move_line_count = fields.Integer(compute="_get_move_line_count")
+
all_lines_reconciled = fields.Boolean(compute='_check_lines_reconciled')
user_id = fields.Many2one('res.users', string='Responsible', required=False, default=lambda self: self.env.user)
cashbox_start_id = fields.Many2one('account.bank.statement.cashbox', string="Starting Cashbox")
@@ -419,7 +426,7 @@ class AccountBankStatementLine(models.Model):
payment_to_unreconcile |= line.payment_id
if st_line.move_name and line.payment_id.payment_reference == st_line.move_name:
#there can be several moves linked to a statement line but maximum one created by the line itself
- aml_to_cancel |= st_line.journal_entry_ids
+ aml_to_cancel |= line
payment_to_cancel |= line.payment_id
aml_to_unbind = aml_to_unbind - aml_to_cancel
@@ -880,6 +887,8 @@ class AccountBankStatementLine(models.Model):
if aml_dict.get('tax_ids') and isinstance(aml_dict['tax_ids'][0], pycompat.integer_types):
# Transform the value in the format required for One2many and Many2many fields
aml_dict['tax_ids'] = [(4, id, None) for id in aml_dict['tax_ids']]
+ if any(line.journal_entry_ids for line in self):
+ raise UserError(_('A selected statement line was already reconciled with an account move.'))
# Fully reconciled moves are just linked to the bank statement
total = self.amount
diff --git a/addons/account/models/company.py b/addons/account/models/company.py
index b15cb4afe0b..44eee5432ae 100644
--- a/addons/account/models/company.py
+++ b/addons/account/models/company.py
@@ -79,8 +79,7 @@ Best Regards,''')
account.write({'code': account.code.rstrip('0').ljust(digits, '0')})
@api.multi
- def write(self, values):
- #restrict the closing of FY if there are still unposted entries
+ def _validate_fiscalyear_lock(self, values):
if values.get('fiscalyear_lock_date'):
nb_draft_entries = self.env['account.move'].search([
('company_id', 'in', [c.id for c in self]),
@@ -88,6 +87,12 @@ Best Regards,''')
('date', '<=', values['fiscalyear_lock_date'])])
if nb_draft_entries:
raise ValidationError(_('There are still unposted entries in the period you want to lock. You should either post or delete them.'))
+
+ @api.multi
+ def write(self, values):
+ #restrict the closing of FY if there are still unposted entries
+ self._validate_fiscalyear_lock(values)
+
# Reflect the change on accounts
for company in self:
digits = values.get('accounts_code_digits') or company.accounts_code_digits
diff --git a/addons/account/report/account_invoice_report.py b/addons/account/report/account_invoice_report.py
index 042455837ce..b028301af6f 100644
--- a/addons/account/report/account_invoice_report.py
+++ b/addons/account/report/account_invoice_report.py
@@ -108,7 +108,7 @@ class AccountInvoiceReport(models.Model):
1 AS nbr,
ai.type, ai.state, pt.categ_id, ai.date_due, ai.account_id, ail.account_id AS account_line_id,
ai.partner_bank_id,
- SUM ((invoice_type.sign * ail.quantity) / (u.factor * u2.factor)) AS product_qty,
+ SUM ((invoice_type.sign * ail.quantity) / u.factor * u2.factor) AS product_qty,
SUM(ail.price_subtotal_signed) AS price_total,
SUM(ABS(ail.price_subtotal_signed)) / CASE
WHEN SUM(ail.quantity / u.factor * u2.factor) <> 0::numeric
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_action.js b/addons/account/static/src/js/reconciliation/reconciliation_action.js
index f9f588a59df..b2c79471929 100644
--- a/addons/account/static/src/js/reconciliation/reconciliation_action.js
+++ b/addons/account/static/src/js/reconciliation/reconciliation_action.js
@@ -257,19 +257,18 @@ var ManualAction = StatementAction.extend({
var handle = event.target.handle;
var method = event.name.indexOf('auto_reconciliation') === -1 ? 'validate' : 'autoReconciliation';
this.model[method](handle).then(function (result) {
- self.renderer.update({
- 'valuenow': self.model.valuenow,
- 'valuemax': self.model.valuemax,
- 'title': self.title,
- 'time': Date.now()-self.time,
- 'notifications': result.notifications,
- });
_.each(result.reconciled, function (handle) {
self._getWidget(handle).destroy();
});
_.each(result.updated, function (handle) {
self._getWidget(handle).update(self.model.getLine(handle));
});
+ self.renderer.update({
+ valuenow: _.compact(_.invoke(self.widgets, 'isDestroyed')).length,
+ valuemax: self.widgets.length,
+ title: self.title,
+ time: Date.now()-self.time,
+ });
self._openFirstLine();
});
},
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js
index f1ef79108c2..f1c6a16cd67 100644
--- a/addons/account/static/src/js/reconciliation/reconciliation_model.js
+++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js
@@ -131,7 +131,7 @@ var StatementModel = BasicModel.extend({
*/
autoReconciliation: function () {
var self = this;
- var ids = _.pluck(_.filter(_.values(this.lines), {'reconciled': false}), 'id');
+ var ids = _.pluck(_.filter(this.lines, {'reconciled': false}), 'id');
return this._rpc({
model: 'account.bank.statement.line',
method: 'reconciliation_widget_auto_reconcile',
@@ -247,7 +247,7 @@ var StatementModel = BasicModel.extend({
var line = this.getLine(handle);
var prop = _.filter(line.reconciliation_proposition, '__focus');
var last = prop[prop.length-1];
- if (last && (!last.account_id || !last.label.length || !last.amount)) {
+ if (last && !this._isValid(last)) {
return $.Deferred().reject();
}
@@ -379,10 +379,12 @@ var StatementModel = BasicModel.extend({
var self = this;
var line = this.getLine(handle);
var prop = _.find(line.reconciliation_proposition, {'id' : id});
- line.reconciliation_proposition = _.filter(line.reconciliation_proposition, function (p) {
- return p.id !== prop.id && p.id !== prop.link && p.link !== prop.id && (!p.link || p.link !== prop.link);
- });
- line.mode = isNaN(id) && !this.avoidCreate ? 'create' : 'match';
+ if (prop) {
+ line.reconciliation_proposition = _.filter(line.reconciliation_proposition, function (p) {
+ return p.id !== prop.id && p.id !== prop.link && p.link !== prop.id && (!p.link || p.link !== prop.link);
+ });
+ }
+ line.mode = (id || line.mode !== "create") && isNaN(id) && !this.avoidCreate ? 'create' : 'match';
var def = this._computeLine(line);
if (line.mode === 'create') {
return def.then(function () {
@@ -870,6 +872,10 @@ var StatementModel = BasicModel.extend({
var ManualModel = StatementModel.extend({
quickCreateFields: ['account_id', 'journal_id', 'amount', 'analytic_account_id', 'label', 'tax_id'],
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
/**
* load data from
* - 'account.move.line' fetch the lines to reconciliate
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
index 003f1a768d8..c082d92764b 100644
--- a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
+++ b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
@@ -102,7 +102,7 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, {
.attr('aria-valuemax', state.valuemax)
.css('width', (state.valuenow/state.valuemax*100) + '%');
- if (state.valuenow === state.valuemax) {
+ if (state.valuenow === state.valuemax && !this.$('.done_message').length) {
var dt = Date.now()-this.time;
var $done = $(qweb.render("reconciliation.done", {
'duration': moment(dt).utc().format(time.strftime_to_moment_format(_t.database.parameters.time_format)),
@@ -129,6 +129,7 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, {
* @param {[object]} notifications
*/
_renderNotifications: function(notifications) {
+ this.$(".notification_area").empty();
for (var i=0; i<notifications.length; i++) {
var $notification = $(qweb.render("reconciliation.notification", {
type: notifications[i].type,
@@ -706,6 +707,7 @@ var ManualLineRenderer = LineRenderer.extend({
_renderCreate: function (state) {
this._super(state);
this.$('.create .create_journal_id').show();
+ this.$('.create .create_journal_id .o_input').addClass('o_required_modifier');
},
});
diff --git a/addons/account/static/src/xml/account_reconciliation.xml b/addons/account/static/src/xml/account_reconciliation.xml
index 33a08794bbc..ea3c111eccc 100644
--- a/addons/account/static/src/xml/account_reconciliation.xml
+++ b/addons/account/static/src/xml/account_reconciliation.xml
@@ -37,7 +37,7 @@
<t t-jquery="div:first" t-operation="attributes">
<attribute name="class">o_manual_statement</attribute>
</t>
- <t t-jquery="h1:last" t-operation="replace"></t>
+ <t t-jquery="h1:last, .progress, .o_automatic_reconciliation" t-operation="replace"></t>
<t t-jquery=".o_view_nocontent p" t-operation="replace"></t>
<t t-jquery=".o_view_nocontent" t-operation="append">
<p><b>Good Job!</b> There is nothing to reconcile.</p>
diff --git a/addons/account/static/tests/reconciliation_tests.js b/addons/account/static/tests/reconciliation_tests.js
index b44c82d6b80..3d87f97cca9 100644
--- a/addons/account/static/tests/reconciliation_tests.js
+++ b/addons/account/static/tests/reconciliation_tests.js
@@ -909,7 +909,7 @@ QUnit.module('account', {
QUnit.test('Reconciliation manual', function (assert) {
- assert.expect(9);
+ assert.expect(8);
var clientAction = new ReconciliationClientAction.ManualAction(null, this.params.options);
@@ -928,8 +928,6 @@ QUnit.module('account', {
clientAction.$('.accounting_view:first .o_reconcile:visible').trigger('click');
- assert.strictEqual(clientAction.$('.progress .progress-bar').attr('aria-valuenow'), "1", "should display a progress bar with 1 reconciled line");
-
assert.strictEqual(clientAction.$('.accounting_view:first thead').text().replace(/[\n\r\s]+/g, ' '),
" Agrolait 101200 ",
"should display the partner and the account code as title");
@@ -943,34 +941,5 @@ QUnit.module('account', {
clientAction.destroy();
});
-
-
- QUnit.test('Reconciliation manual validate all', function (assert) {
- assert.expect(6);
-
- var clientAction = new ReconciliationClientAction.ManualAction(null, this.params.options);
-
- testUtils.addMockEnvironment(clientAction, {
- 'data': this.params.data,
- session: this.params.session,
- });
-
- clientAction.prependTo($('#qunit-fixture'));
-
- assert.strictEqual(clientAction.$('.o_reconciliation_line[data-mode="match"]').length, 0, "should have every widgets in 'inactive' mode");
- assert.strictEqual(clientAction.$('.o_reconciliation_line').length, 5, "should have 5 widgets to reconciled");
- assert.strictEqual(clientAction.$('.o_reconciliation_line button.o_reconcile:visible').length, 3, "should have 3 widgets who display 'reconcile' button");
-
- var e = $.Event("keyup");
- e.which = 13; // # Enter code value
- e.ctrlKey = true; // Ctrl key pressed
- $("body").trigger(e);
-
- assert.strictEqual(clientAction.$('.o_reconciliation_line').length, 3, "should have 2 already reconciled widgets");
- assert.strictEqual(clientAction.$('.progress .progress-bar').attr('aria-valuenow'), "2", "should display a progress bar with 2 reconciled line");
- assert.strictEqual(clientAction.$('.o_reconciliation_line[data-mode="match"]').length, 1, "should display the 'match' mode for the first line");
-
- clientAction.destroy();
- });
});
});
diff --git a/addons/account/views/account_view.xml b/addons/account/views/account_view.xml
index 5bb2e01b651..da4b7cf04fc 100644
--- a/addons/account/views/account_view.xml
+++ b/addons/account/views/account_view.xml
@@ -553,8 +553,9 @@
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="button_journal_entries"
string="Journal Entries" type="object"
- attrs="{'invisible':[('move_line_ids','=',[])]}" icon="fa-bars"/>
- <field name="move_line_ids" invisible="1"/>
+ attrs="{'invisible':[('move_line_count','=', 0)]}" icon="fa-bars" />
+ <field name="move_line_count" invisible="1"/>
+
</div>
<div class="oe_title oe_inline">
<label for="name" class="oe_edit_only"/>
@@ -565,7 +566,7 @@
<field name="journal_type" invisible="1"/>
<field name="cashbox_start_id" invisible="1"/>
<field name="cashbox_end_id" invisible="1"/>
- <field name="journal_id" domain="[('type', '=', journal_type)]" attrs="{'readonly': [('move_line_ids', '!=', [])]}" widget="selection"/>
+ <field name="journal_id" domain="[('type', '=', journal_type)]" attrs="{'readonly': [('move_line_count','!=', 0)]}" widget="selection"/>
<field name="date"/>
<field name='company_id' options="{'no_create': True}" groups="base.group_multi_company" />
<field name="currency_id" invisible="1"/>
diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
index 825a880b62c..533f84a8d82 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -58,6 +58,9 @@ class AuthSignupHome(Home):
else:
login = qcontext.get('login')
assert login, "No login provided."
+ _logger.info(
+ "Password reset attempt for <%s> by user <%s> from %s",
+ login, request.env.user.login, request.httprequest.remote_addr)
request.env['res.users'].sudo().reset_password(login)
qcontext['message'] = _("An email has been sent with credentials to reset your password")
except SignupError:
diff --git a/addons/auth_signup/models/res_users.py b/addons/auth_signup/models/res_users.py
index d99961076be..05d52596c85 100644
--- a/addons/auth_signup/models/res_users.py
+++ b/addons/auth_signup/models/res_users.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+import logging
from ast import literal_eval
@@ -11,6 +12,7 @@ from odoo.tools.misc import ustr
from odoo.addons.base.ir.ir_mail_server import MailDeliveryException
from odoo.addons.auth_signup.models.res_partner import SignupError, now
+_logger = logging.getLogger(__name__)
class ResUsers(models.Model):
_inherit = 'res.users'
@@ -134,6 +136,7 @@ class ResUsers(models.Model):
if not user.email:
raise UserError(_("Cannot send email: user %s has no email address.") % user.name)
template.with_context(lang=user.lang).send_mail(user.id, force_send=True, raise_exception=True)
+ _logger.info("Password reset email sent for user <%s> to <%s>", user.login, user.email)
@api.model
def create(self, values):
diff --git a/addons/barcodes/static/src/js/barcode_form_view.js b/addons/barcodes/static/src/js/barcode_form_view.js
index 678b23444a8..69a59fdaafa 100644
--- a/addons/barcodes/static/src/js/barcode_form_view.js
+++ b/addons/barcodes/static/src/js/barcode_form_view.js
@@ -2,6 +2,7 @@ odoo.define('barcodes.FormView', function (require) {
"use strict";
var BarcodeEvents = require('barcodes.BarcodeEvents'); // handle to trigger barcode on bus
+var concurrency = require('web.concurrency');
var core = require('web.core');
var Dialog = require('web.Dialog');
var FormController = require('web.FormController');
@@ -34,6 +35,8 @@ FormController.include({
}
}
};
+
+ this.barcodeMutex = new concurrency.Mutex();
this._barcodeStartListening();
},
destroy: function () {
@@ -202,34 +205,36 @@ FormController.include({
* @returns {Deferred}
*/
_barcodeScanned: function (barcode, target) {
- var prefixed = _.any(BarcodeEvents.ReservedBarcodePrefixes,
- function (reserved) {return barcode.indexOf(reserved) === 0;});
- var hasCommand = false;
var self = this;
- var defs = [];
- for (var k in this.activeBarcode) {
- var activeBarcode = this.activeBarcode[k];
- // Handle the case where there are several barcode widgets on the same page. Since the
- // event is global on the page, all barcode widgets will be triggered. However, we only
- // want to keep the event on the target widget.
- if (self.target && !$.contains(target, self.target.el)) {
- continue;
- }
+ return this.barcodeMutex.exec(function () {
+ var prefixed = _.any(BarcodeEvents.ReservedBarcodePrefixes,
+ function (reserved) {return barcode.indexOf(reserved) === 0;});
+ var hasCommand = false;
+ var defs = [];
+ for (var k in self.activeBarcode) {
+ var activeBarcode = self.activeBarcode[k];
+ // Handle the case where there are several barcode widgets on the same page. Since the
+ // event is global on the page, all barcode widgets will be triggered. However, we only
+ // want to keep the event on the target widget.
+ if (self.target && !$.contains(target, self.target.el)) {
+ continue;
+ }
- var methods = this.activeBarcode[k].commands;
- var method = prefixed ? methods[barcode] : methods.barcode;
- if (method) {
- if (prefixed) {
- hasCommand = true;
+ var methods = self.activeBarcode[k].commands;
+ var method = prefixed ? methods[barcode] : methods.barcode;
+ if (method) {
+ if (prefixed) {
+ hasCommand = true;
+ }
+ defs.push(self._barcodeActiveScanned(method, barcode, activeBarcode));
}
- defs.push(this._barcodeActiveScanned(method, barcode, activeBarcode));
}
- }
- if (prefixed && !hasCommand) {
- return this.do_warn(_t('Error : Barcode command is undefined'), barcode);
- }
- return $.when.apply($, defs).then(function () {
- self.update({}, {reload: false});
+ if (prefixed && !hasCommand) {
+ self.do_warn(_t('Error : Barcode command is undefined'), barcode);
+ }
+ return $.when.apply($, defs).then(function () {
+ self.update({}, {reload: false});
+ });
});
},
/**
@@ -314,6 +319,8 @@ FormRenderer.include({
commands['O-BTN.' + node.attrs.barcode_trigger] = function () {
if (!$button.hasClass('o_invisible_modifier')) {
$button.click();
+ } else {
+ this.do_warn(_t('Action currently unavailable'));
}
return $.when();
};
diff --git a/addons/base_automation/views/base_automation_view.xml b/addons/base_automation/views/base_automation_view.xml
index fa8c4b5eab2..a81dd04d75b 100644
--- a/addons/base_automation/views/base_automation_view.xml
+++ b/addons/base_automation/views/base_automation_view.xml
@@ -15,6 +15,13 @@
attrs="{'invisible':[('menu_ir_values_id','=',False)]}"
help="Remove the contextual action related to this server action"/>
</xpath>
+ <div class="oe_title" position="before">
+ <div class="oe_button_box" name="button_box">
+ <button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
+ <field name="active" widget="boolean_button"/>
+ </button>
+ </div>
+ </div>
<xpath expr="//group[@name='action_wrapper']" position="inside">
<group>
<field name="trigger"/>
diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py
index 4a6d67bd2bf..face994b75e 100644
--- a/addons/fleet/models/fleet_vehicle.py
+++ b/addons/fleet/models/fleet_vehicle.py
@@ -65,7 +65,7 @@ class FleetVehicle(models.Model):
contract_renewal_name = fields.Text(compute='_compute_contract_reminder', string='Name of contract to renew soon', multi='contract_info')
contract_renewal_total = fields.Text(compute='_compute_contract_reminder', string='Total of contracts due or overdue minus one',
multi='contract_info')
- car_value = fields.Float(string="Catalog Value (VAT incl.)", help='Value of the bought vehicle')
+ car_value = fields.Float(string="Catalog Value (VAT Incl.)", help='Value of the bought vehicle')
residual_value = fields.Float()
_sql_constraints = [
diff --git a/addons/google_spreadsheet/views/base_config_settings_views.xml b/addons/google_spreadsheet/views/base_config_settings_views.xml
index 14bda91e373..6afd8ddacda 100644
--- a/addons/google_spreadsheet/views/base_config_settings_views.xml
+++ b/addons/google_spreadsheet/views/base_config_settings_views.xml
@@ -8,13 +8,10 @@
<field name="arch" type="xml">
<xpath expr="//div[@id='msg_module_google_spreadsheet']" position="replace">
<div class="content-group" attrs="{'invisible': [('module_google_spreadsheet','=',False)]}">
- <div class="row mt16">
- <label for="google_drive_authorization_code" class="col-md-3 o_light_label"/>
- <field name="google_drive_authorization_code"/>
- </div>
- <a type="button" class="btn-link" target="_blank"><i class="fa fa-fw fa-arrow-right"/>
- <field name="google_drive_uri_copy" widget="url" text="Generate Code"/>
- </a>
+ <div class="content-group mt16">
+ Please use the settings of Google Drive
+ on the left or above.
+ </div>
</div>
</xpath>
</field>
diff --git a/addons/hr/models/hr.py b/addons/hr/models/hr.py
index 7bd91ccfa95..ccfe751025b 100644
--- a/addons/hr/models/hr.py
+++ b/addons/hr/models/hr.py
@@ -32,7 +32,7 @@ class Job(models.Model):
_description = "Job Position"
_inherit = ['mail.thread']
- name = fields.Char(string='Job Title', required=True, index=True, translate=True)
+ name = fields.Char(string='Job Position', required=True, index=True, translate=True)
expected_employees = fields.Integer(compute='_compute_employees', string='Total Forecasted Employees', store=True,
help='Expected number of employees for this job position after new recruitment.')
no_of_employee = fields.Integer(compute='_compute_employees', string="Current Number of Employees", store=True,
@@ -161,7 +161,7 @@ class Employee(models.Model):
work_email = fields.Char('Work Email')
work_location = fields.Char('Work Location')
# employee in company
- job_id = fields.Many2one('hr.job', 'Job Title')
+ job_id = fields.Many2one('hr.job', 'Job Position')
department_id = fields.Many2one('hr.department', 'Department')
parent_id = fields.Many2one('hr.employee', 'Manager')
child_ids = fields.One2many('hr.employee', 'parent_id', string='Subordinates')
diff --git a/addons/hr/views/hr_views.xml b/addons/hr/views/hr_views.xml
index bdbe127e84c..d82d63bb350 100644
--- a/addons/hr/views/hr_views.xml
+++ b/addons/hr/views/hr_views.xml
@@ -352,8 +352,8 @@
<label for="name" class="oe_edit_only"/>
<h1><field name="name" placeholder="e.g. Sales Manager"/></h1>
</div>
- <group name="employee_data">
- <group>
+ <group>
+ <group string="Recruitment" name="recruitment">
<field name="department_id"/>
<field name="no_of_recruitment"/>
</group>
diff --git a/addons/hr_contract/models/hr_contract.py b/addons/hr_contract/models/hr_contract.py
index 5027e40a0f7..086d5dc94db 100644
--- a/addons/hr_contract/models/hr_contract.py
+++ b/addons/hr_contract/models/hr_contract.py
@@ -57,14 +57,17 @@ class Contract(models.Model):
employee_id = fields.Many2one('hr.employee', string='Employee')
department_id = fields.Many2one('hr.department', string="Department")
type_id = fields.Many2one('hr.contract.type', string="Contract Type", required=True, default=lambda self: self.env['hr.contract.type'].search([], limit=1))
- job_id = fields.Many2one('hr.job', string='Job Title')
- date_start = fields.Date('Start Date', required=True, default=fields.Date.today)
- date_end = fields.Date('End Date')
- trial_date_end = fields.Date('End of Trial Period')
+ job_id = fields.Many2one('hr.job', string='Job Position')
+ date_start = fields.Date('Start Date', required=True, default=fields.Date.today,
+ help="Start date of the contract.")
+ date_end = fields.Date('End Date',
+ help="End date of the contract (if it's a fixed-term contract).")
+ trial_date_end = fields.Date('End of Trial Period',
+ help="End date of the trial period (if there is one).")
resource_calendar_id = fields.Many2one(
'resource.calendar', 'Working Schedule',
default=lambda self: self.env['res.company']._company_default_get().resource_calendar_id.id)
- wage = fields.Monetary('Wage', digits=(16, 2), required=True, help="The monthly gross wage of the employee.")
+ wage = fields.Monetary('Wage', digits=(16, 2), required=True, help="Employee's monthly gross wage.")
advantages = fields.Text('Advantages')
notes = fields.Text('Notes')
state = fields.Selection([
@@ -73,13 +76,17 @@ class Contract(models.Model):
('pending', 'To Renew'),
('close', 'Expired'),
('cancel', 'Cancelled')
- ], string='Status', track_visibility='onchange', help='Status of the contract', default='draft')
+ ], string='Status', group_expand='_expand_states',
+ track_visibility='onchange', help='Status of the contract', default='draft')
company_id = fields.Many2one('res.company', default=lambda self: self.env.user.company_id)
- currency_id = fields.Many2one(string="Currency", related='company_id.currency_id')
+ currency_id = fields.Many2one(string="Currency", related='company_id.currency_id', readonly=True)
permit_no = fields.Char('Work Permit No', related="employee_id.permit_no")
visa_no = fields.Char('Visa No', related="employee_id.visa_no")
visa_expire = fields.Date('Visa Expire Date', related="employee_id.visa_expire")
+ def _expand_states(self, states, domain, order):
+ return [key for key, val in type(self).state.selection]
+
@api.onchange('employee_id')
def _onchange_employee_id(self):
if self.employee_id:
diff --git a/addons/hr_contract/views/hr_contract_views.xml b/addons/hr_contract/views/hr_contract_views.xml
index 5c70fd640a5..b133e828695 100644
--- a/addons/hr_contract/views/hr_contract_views.xml
+++ b/addons/hr_contract/views/hr_contract_views.xml
@@ -5,8 +5,12 @@
<field name="name">Contracts</field>
<field name="res_model">hr.contract</field>
<field name="view_type">form</field>
- <field name="view_mode">tree,form</field>
- <field name="context">{'search_default_employee_id': [active_id], 'default_employee_id': active_id}</field>
+ <field name="view_mode">kanban,tree,form</field>
+ <field name="context">{
+ 'search_default_employee_id': [active_id],
+ 'default_employee_id': active_id,
+ 'search_default_group_by_state': 1
+ }</field>
</record>
<record id="hr_hr_employee_view_form2" model="ir.ui.view">
@@ -68,6 +72,7 @@
<filter string="Employee" domain="[]" context="{'group_by':'employee_id'}"/>
<filter string="Job" domain="[]" context="{'group_by':'job_id'}"/>
<filter string="Contract Type" domain="[]" context="{'group_by':'type_id'}"/>
+ <filter string="State" name='group_by_state' domain="[]" context="{'group_by': 'state'}"/>
</group>
</search>
</field>
@@ -145,8 +150,8 @@
<tree string="Contracts" decoration-bf="message_needaction == True">
<field name="name"/>
<field name="employee_id"/>
- <field name="type_id"/>
<field name="job_id"/>
+ <field name="type_id"/>
<field name="resource_calendar_id"/>
<field name="date_start"/>
<field name="date_end"/>
@@ -156,56 +161,50 @@
</field>
</record>
- <record id="view_hr_contract_kanban" model="ir.ui.view">
- <field name="name">hr.contract.kanban</field>
- <field name="model">hr.contract</field>
- <field name="arch" type="xml">
- <kanban>
- <field name="employee_id"/>
- <field name="date_end"/>
- <field name="date_start"/>
- <templates>
+ <record id="hr_contract_view_kanban" model="ir.ui.view">
+ <field name="name">hr.contract.kanban</field>
+ <field name="model">hr.contract</field>
+ <field name="arch" type="xml">
+ <kanban class="o_kanban_small_column">
+ <field name="employee_id"/>
+ <templates>
<t t-name="kanban-box">
- <div class="oe_kanban_global_click">
- <div class="row mb4">
- <div class="col-xs-8">
- <span>
- <strong><field name="name"/></strong>
- </span>
+ <div class="oe_kanban_card oe_kanban_global_click">
+ <div class="o_dropdown_kanban dropdown" groups="base.group_user">
+ <a class="dropdown-toggle btn" data-toggle="dropdown" href="#" >
+ <span class="fa fa-bars fa-lg"/>
+ </a>
+ <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
+ <t t-if="widget.editable"><li><a type="edit">Edit Contract</a></li></t>
+ <t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
+ </ul>
</div>
- <div class="col-xs-4">
- <span class="pull-right">
- <field name="state" widget="kanban_label_selection" options="{'classes': {'pending': 'warning', 'close': 'danger', 'draft': 'default'}}"/>
- </span>
+ <div class="oe_kanban_content">
+ <div>
+ <strong><field name="name"/></strong>
+ </div>
+ <div class="text-muted">
+ <field name="job_id"/>
+ </div>
+ <div class="oe_kanban_bottom_right">
+ <img t-att-src="kanban_image('hr.employee', 'image_medium', record.employee_id.raw_value)" t-att-title="record.employee_id.value" width="24" height="24" class="oe_kanban_avatar pull-right"/>
+ </div>
</div>
+ <div class="oe_clear"></div>
</div>
- <div class="o_kanban_image mt8">
- <img t-att-src="kanban_image('hr.employee', 'image_medium', record.employee_id.raw_value)"/>
- </div>
- <div class="oe_kanban_details">
- <ul>
- <li><strong><field name="employee_id"/></strong></li>
- <li><field name="job_id"/></li>
- <li><field name="department_id"/></li>
- <li><field name="type_id"/></li>
- <li t-if="record.date_end.value &amp;&amp; record.date_start.value"><i class="fa fa-calendar"/> <field name="date_start"/> - <field name="date_end"/></li>
- </ul>
- </div>
- </div>
</t>
- </templates>
- </kanban>
-
- </field>
- </record>
+ </templates>
+ </kanban>
+ </field>
+ </record>
<record id="action_hr_contract" model="ir.actions.act_window">
<field name="name">Contracts</field>
<field name="res_model">hr.contract</field>
<field name="view_type">form</field>
- <field name="view_mode">tree,kanban,form</field>
- <field name="domain">[]</field>
- <field name="context">{'search_default_current':1}</field>
+ <field name="view_mode">kanban,tree,form</field>
+ <field name="domain">[('employee_id', '!=', False)]</field>
+ <field name="context">{'search_default_current':1, 'search_default_group_by_state': 1}</field>
<field name="search_view_id" ref="hr_contract_view_search"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
@@ -271,4 +270,5 @@
sequence="4"
groups="hr.group_hr_manager"/>
+
</odoo>
diff --git a/addons/hr_payroll/models/hr_contract.py b/addons/hr_payroll/models/hr_contract.py
index 054782c406d..6aebe4134de 100644
--- a/addons/hr_payroll/models/hr_contract.py
+++ b/addons/hr_payroll/models/hr_contract.py
@@ -21,8 +21,9 @@ class HrContract(models.Model):
('weekly', 'Weekly'),
('bi-weekly', 'Bi-weekly'),
('bi-monthly', 'Bi-monthly'),
- ], string='Scheduled Pay', index=True, default='monthly')
- resource_calendar_id = fields.Many2one(required=True)
+ ], string='Scheduled Pay', index=True, default='monthly',
+ help="Defines the frequency of the wage payment.")
+ resource_calendar_id = fields.Many2one(required=True, help="Employee's working schedule.")
@api.multi
def get_all_structures(self):
diff --git a/addons/hr_payroll/security/ir.model.access.csv b/addons/hr_payroll/security/ir.model.access.csv
index 443d9c77588..65def2231fa 100644
--- a/addons/hr_payroll/security/ir.model.access.csv
+++ b/addons/hr_payroll/security/ir.model.access.csv
@@ -1,5 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_payroll_structure,hr.payroll.structure,model_hr_payroll_structure,hr_payroll.group_hr_payroll_user,1,1,1,1
+access_hr_payroll_structure_hr_user,hr.payroll.structure.hr.user,model_hr_payroll_structure,hr.group_hr_user,1,0,0,0
access_hr_contribution_register,hr.contribution.register,model_hr_contribution_register,hr_payroll.group_hr_payroll_user,1,1,1,1
access_hr_salary_rule_category,hr.salary.rule.category,model_hr_salary_rule_category,hr_payroll.group_hr_payroll_user,1,1,1,1
access_hr_payslip,hr.payslip,model_hr_payslip,hr_payroll.group_hr_payroll_user,1,1,1,1
@@ -10,3 +11,4 @@ access_hr_payslip_run,hr.payslip.run,model_hr_payslip_run,hr_payroll.group_hr_pa
access_hr_rule_input_officer,hr.rule.input.office,model_hr_rule_input,hr_payroll.group_hr_payroll_user,1,1,1,1
access_hr_salary_rule_user,hr.salary.rule.user,model_hr_salary_rule,hr_payroll.group_hr_payroll_user,1,1,1,1
access_hr_contract_advantage_template,hr.contract.advantage.template.user,model_hr_contract_advantage_template,hr_payroll.group_hr_payroll_user,1,1,1,1
+access_hr_contract_advantage_template_hr_user,hr.contract.advantage.template.hr.user,model_hr_contract_advantage_template,hr.group_hr_user,1,0,0,0
diff --git a/addons/hr_payroll/views/hr_contract_views.xml b/addons/hr_payroll/views/hr_contract_views.xml
index 03d0b09cef2..71acff3c13a 100644
--- a/addons/hr_payroll/views/hr_contract_views.xml
+++ b/addons/hr_payroll/views/hr_contract_views.xml
@@ -16,7 +16,7 @@
<field name="struct_id" required="1"/>
</xpath>
<xpath expr="//field[@name='type_id']" position="before">
- <field name="company_id"/>
+ <field name="company_id" groups="base.group_multi_company"/>
<field name="currency_id" invisible="1"/>
</xpath>
<xpath expr="//field[@name='resource_calendar_id']" position="after">
diff --git a/addons/hr_recruitment/models/hr_job.py b/addons/hr_recruitment/models/hr_job.py
index e7648bcfe75..0c6c643b118 100644
--- a/addons/hr_recruitment/models/hr_job.py
+++ b/addons/hr_recruitment/models/hr_job.py
@@ -20,7 +20,8 @@ class Job(models.Model):
'hr.employee', related='department_id.manager_id', string="Department Manager",
readonly=True, store=True)
user_id = fields.Many2one('res.users', "Recruitment Responsible", track_visibility='onchange')
- hr_responsible_id = fields.Many2one('res.users', "HR Responsible", track_visibility='onchange')
+ hr_responsible_id = fields.Many2one('res.users', "HR Responsible", track_visibility='onchange',
+ help="Person responsible of validating the employee's contracts.")
document_ids = fields.One2many('ir.attachment', compute='_compute_document_ids', string="Applications")
documents_count = fields.Integer(compute='_compute_document_ids', string="Documents")
alias_id = fields.Many2one(
diff --git a/addons/hr_recruitment/views/hr_recruitment_views.xml b/addons/hr_recruitment/views/hr_recruitment_views.xml
index c487180c521..6882376b1da 100644
--- a/addons/hr_recruitment/views/hr_recruitment_views.xml
+++ b/addons/hr_recruitment/views/hr_recruitment_views.xml
@@ -438,23 +438,21 @@
<field name="model">hr.job</field>
<field name="inherit_id" ref="hr.view_hr_job_form"/>
<field name="arch" type="xml">
- <group name="employee_data" position="inside">
- <group>
- <field name="address_id" context="{'show_address': 1}" domain= "[('is_company', '=', True )]" options="{'always_reload': True}"/>
- </group>
- </group>
<xpath expr="//field[@name='department_id']" position="after">
- <label for="alias_name" string="Specific Email Address" attrs="{'invisible': [('alias_domain', '=', False)]}" help="Define a specific contact address for this job position. If you keep it empty, the default email address will be used which is in human resources settings"/>
+ <field name="address_id" context="{'show_address': 1}" domain= "[('is_company', '=', True )]" options="{'always_reload': True}"/>
+ <label for="alias_name" string="Email alias" attrs="{'invisible': [('alias_domain', '=', False)]}" help="Define a specific contact address for this job position. If you keep it empty, the default email address will be used which is in human resources settings"/>
<div name="alias_def" attrs="{'invisible': [('alias_domain', '=', False)]}">
<field name="alias_id" class="oe_read_only" string="Email Alias" required="0"/>
<div class="oe_edit_only" name="edit_alias">
<field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
</div>
</div>
- </xpath>
- <xpath expr="//field[@name='department_id']" position="after">
<field name="user_id"/>
- <field name="hr_responsible_id"/>
+ </xpath>
+ <xpath expr="//group[@name='recruitment']" position="after">
+ <group string="Offer" name="offer">
+ <field name="hr_responsible_id"/>
+ </group>
</xpath>
<div name="button_box" position="inside">
<button class="oe_stat_button"
diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py
index 3c3cdecff9e..74704a459f2 100644
--- a/addons/hr_timesheet/models/hr_timesheet.py
+++ b/addons/hr_timesheet/models/hr_timesheet.py
@@ -7,13 +7,10 @@ from odoo import api, fields, models
class AccountAnalyticLine(models.Model):
_inherit = 'account.analytic.line'
- def _default_employee_id(self):
- return self.env.user.employee_ids[0]
-
task_id = fields.Many2one('project.task', 'Task')
project_id = fields.Many2one('project.project', 'Project', domain=[('allow_timesheets', '=', True)])
- employee_id = fields.Many2one('hr.employee', "Employee", default=_default_employee_id)
+ employee_id = fields.Many2one('hr.employee', "Employee")
department_id = fields.Many2one('hr.department', "Department", related='employee_id.department_id', store=True, readonly=True)
@api.onchange('project_id')
@@ -27,6 +24,12 @@ class AccountAnalyticLine(models.Model):
@api.model
def create(self, vals):
vals = self._update_timesheet_values(vals)
+ if not vals.get('employee_id') and vals.get('project_id'): # compute employee only for timesheet lines, makes no sense for other lines
+ if vals.get('user_id'):
+ ts_user_id = vals['user_id']
+ else:
+ ts_user_id = self.env.user.id
+ vals['employee_id'] = self.env['hr.employee'].search([('user_id', '=', ts_user_id)], limit=1).id
return super(AccountAnalyticLine, self).create(vals)
@api.multi
diff --git a/addons/hr_timesheet/tests/__init__.py b/addons/hr_timesheet/tests/__init__.py
new file mode 100644
index 00000000000..2562aceb885
--- /dev/null
+++ b/addons/hr_timesheet/tests/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import test_timesheet
diff --git a/addons/hr_timesheet/tests/test_timesheet.py b/addons/hr_timesheet/tests/test_timesheet.py
new file mode 100644
index 00000000000..e744d4341f7
--- /dev/null
+++ b/addons/hr_timesheet/tests/test_timesheet.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo.tests.common import TransactionCase
+from odoo.exceptions import AccessError
+
+
+class TestTimesheet(TransactionCase):
+
+ def setUp(self):
+ super(TestTimesheet, self).setUp()
+
+ self.project_customer = self.env['project.project'].create({
+ 'name': 'Project X',
+ 'allow_timesheets': True,
+ 'use_tasks': True,
+ })
+ self.task1 = self.env['project.task'].create({
+ 'name': 'Task One',
+ 'priority': '0',
+ 'kanban_state': 'normal',
+ 'project_id': self.project_customer.id,
+ })
+ self.task2 = self.env['project.task'].create({
+ 'name': 'Task Two',
+ 'priority': '1',
+ 'kanban_state': 'done',
+ 'project_id': self.project_customer.id,
+ })
+ # users
+ self.user_employee = self.env['res.users'].create({
+ 'name': 'User Employee',
+ 'login': 'user_employee',
+ 'email': 'useremployee@test.com',
+ 'groups_id': [(4, self.ref('hr_timesheet.group_hr_timesheet_user'))],
+ })
+ self.user_employee2 = self.env['res.users'].create({
+ 'name': 'User Employee 2',
+ 'login': 'user_employee2',
+ 'email': 'useremployee2@test.com',
+ 'groups_id': [(4, self.ref('hr_timesheet.group_hr_timesheet_user'))],
+ })
+ self.user_manager = self.env['res.users'].create({
+ 'name': 'User Officer',
+ 'login': 'user_manager',
+ 'email': 'usermanager@test.com',
+ 'groups_id': [(4, self.ref('hr_timesheet.group_timesheet_manager'))],
+ })
+ # employees
+ self.empl_employee = self.env['hr.employee'].create({
+ 'name': 'User Empl Employee',
+ 'user_id': self.user_employee.id,
+ })
+ self.empl_employee2 = self.env['hr.employee'].create({
+ 'name': 'User Empl Employee 2',
+ 'user_id': self.user_employee2.id,
+ })
+ self.empl_manager = self.env['hr.employee'].create({
+ 'name': 'User Empl Officer',
+ 'user_id': self.user_manager.id,
+ })
+
+ def test_log_timesheet(self):
+ """ Test when log timesheet : check analytic account, user and employee are correctly set. """
+ Timesheet = self.env['account.analytic.line']
+ # employee 1 log some timesheet on task 1
+ timesheet1 = Timesheet.sudo(self.user_employee.id).create({
+ 'project_id': self.project_customer.id,
+ 'task_id': self.task1.id,
+ 'name': 'my first timesheet',
+ 'unit_amount': 4,
+ })
+ self.assertEquals(timesheet1.account_id, self.project_customer.analytic_account_id, 'Analytic account should be the same as the project')
+ self.assertEquals(timesheet1.employee_id, self.empl_employee, 'Employee should be the one of the current user')
+
+ # employee 1 cannot log timesheet for employee 2
+ with self.assertRaises(AccessError):
+ timesheet2 = Timesheet.sudo(self.user_employee.id).create({
+ 'project_id': self.project_customer.id,
+ 'task_id': self.task1.id,
+ 'name': 'a second timesheet but for employee 2',
+ 'unit_amount': 3,
+ 'employee_id': self.empl_employee2.id,
+ })
+
+ # manager log timesheet for employee 2
+ timesheet3 = Timesheet.sudo(self.user_manager.id).create({
+ 'project_id': self.project_customer.id,
+ 'task_id': self.task1.id,
+ 'name': 'a second timesheet but for employee 2',
+ 'unit_amount': 7,
+ 'employee_id': self.empl_employee2.id,
+ })
+ timesheet3._onchange_employee_id()
+ self.assertEquals(timesheet3.user_id, self.user_employee2, 'Timesheet user should be the one linked to the given employee')
+
+ def test_log_access_rights(self):
+ """ Test access rights : user can update its own timesheets only, and manager can change all """
+ # employee 1 log some timesheet on task 1
+ Timesheet = self.env['account.analytic.line']
+ timesheet1 = Timesheet.sudo(self.user_employee.id).create({
+ 'project_id': self.project_customer.id,
+ 'task_id': self.task1.id,
+ 'name': 'my first timesheet',
+ 'unit_amount': 4,
+ })
+ # then employee 2 try to modify it
+ with self.assertRaises(AccessError):
+ timesheet1.sudo(self.user_employee2.id).write({
+ 'name': 'i try to update this timesheet',
+ 'unit_amount': 2,
+ })
+ # manager can modify all timesheet
+ timesheet1.sudo(self.user_manager.id).write({
+ 'unit_amount': 8,
+ 'employee_id': self.empl_employee2.id,
+ })
+ self.assertEquals(timesheet1.user_id, self.user_employee2, 'Changing timesheet employee should change the related user')
diff --git a/addons/im_livechat/models/im_livechat_channel.py b/addons/im_livechat/models/im_livechat_channel.py
index 85ca245c32c..51ebc87a908 100644
--- a/addons/im_livechat/models/im_livechat_channel.py
+++ b/addons/im_livechat/models/im_livechat_channel.py
@@ -167,7 +167,7 @@ class ImLivechatChannel(models.Model):
operator_partner_id = user.partner_id.id
# partner to add to the mail.channel
channel_partner_to_add = [(4, operator_partner_id)]
- if self.env.uid: # if the user if logged (portal user), he can be identify
+ if self.env.user and self.env.user.active: # valid session user (not public)
channel_partner_to_add.append((4, self.env.user.partner_id.id))
# create the session, and add the link with the given channel
mail_channel = self.env["mail.channel"].with_context(mail_create_nosubscribe=False).sudo().create({
diff --git a/addons/im_livechat/views/im_livechat_channel_templates.xml b/addons/im_livechat/views/im_livechat_channel_templates.xml
index 2c0205a97ea..ff9b5ab1e25 100644
--- a/addons/im_livechat/views/im_livechat_channel_templates.xml
+++ b/addons/im_livechat/views/im_livechat_channel_templates.xml
@@ -113,19 +113,24 @@
<!-- Odoo JS Framework -->
<script type="text/javascript" src="/web/static/src/js/boot.js"></script>
<script type="text/javascript" src="/web/static/src/js/services/config.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/core/abstract_service.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/class.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/core/collections.js"/>
<script type="text/javascript" src="/web/static/src/js/core/translation.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/ajax.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/time.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/mixins.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/core/rpc.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/widget.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/registry.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/session.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/core/concurrency.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/utils.js"></script>
- <script type="text/javascript" src="/web/static/src/js/core/bus.js"></script>
- <script type="text/javascript" src="/web/static/src/js/core/local_storage.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/qweb.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/core/bus.js"></script>
<script type="text/javascript" src="/web/static/src/js/services/core.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/core/local_storage.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/services/local_storage_service.js"></script>
<!-- Bus, Mail, Livechat -->
<script type="text/javascript" src="/bus/static/src/js/bus.js"></script>
<script type="text/javascript" src="/mail/static/src/js/chat_window.js"></script>
diff --git a/addons/l10n_be_hr_payroll/data/hr.salary.rule.csv b/addons/l10n_be_hr_payroll/data/hr.salary.rule.csv
index 9b42ade6bf8..ba1e56a9114 100644
--- a/addons/l10n_be_hr_payroll/data/hr.salary.rule.csv
+++ b/addons/l10n_be_hr_payroll/data/hr.salary.rule.csv
@@ -1,1422 +1,1422 @@
-"id","amount_select","condition_range_min","condition_range_max","amount_percentage","amount_fix","name","category_id","sequence","code","parent_rule_id/id","condition_select","condition_range","amount_percentage_base","register_id/id"
-1,"fix",0,555,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-2,"fix",555,570,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-3,"fix",570,585,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-4,"fix",585,600,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-5,"fix",600,615,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-6,"fix",615,630,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-7,"fix",630,645,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-8,"fix",645,660,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-9,"fix",660,675,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-10,"fix",675,690,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-11,"fix",690,705,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-12,"fix",705,720,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-13,"fix",720,735,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-14,"fix",735,750,,-0.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-15,"fix",750,765,,-4.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-16,"fix",765,780,,-7.63,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-17,"fix",780,795,,-11.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-18,"fix",795,810,,-14.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-19,"fix",810,825,,-18.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-20,"fix",825,840,,-21.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-21,"fix",840,855,,-25.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-22,"fix",855,870,,-29.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-23,"fix",870,885,,-32.63,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-24,"fix",885,900,,-36.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-25,"fix",900,915,,-39.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-26,"fix",915,930,,-43.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-27,"fix",930,945,,-46.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-28,"fix",945,960,,-50.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-29,"fix",960,975,,-54.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-30,"fix",975,990,,-57.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-31,"fix",990,1005,,-61.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-32,"fix",1005,1020,,-64.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-33,"fix",1020,1035,,-68.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-34,"fix",1035,1050,,-71.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-35,"fix",1050,1065,,-75.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-36,"fix",1065,1080,,-79.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-37,"fix",1080,1095,,-82.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-38,"fix",1095,1110,,-86.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-39,"fix",1110,1125,,-89.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-40,"fix",1125,1140,,-93.33,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-41,"fix",1140,1155,,-96.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-42,"fix",1155,1170,,-100.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-43,"fix",1170,1185,,-104.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-44,"fix",1185,1200,,-107.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-45,"fix",1200,1215,,-111.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-46,"fix",1215,1230,,-115.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-47,"fix",1230,1245,,-120.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-48,"fix",1245,1260,,-124.53,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-49,"fix",1260,1275,,-128.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-50,"fix",1275,1290,,-133.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-51,"fix",1290,1305,,-137.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-52,"fix",1305,1320,,-143.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-53,"fix",1320,1335,,-148.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-54,"fix",1335,1350,,-154.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-55,"fix",1350,1365,,-160.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-56,"fix",1365,1380,,-165.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-57,"fix",1380,1395,,-171.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-58,"fix",1395,1410,,-177.38,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-59,"fix",1410,1425,,-183.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-60,"fix",1425,1440,,-188.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-61,"fix",1440,1455,,-194.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-62,"fix",1455,1470,,-200.23,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-63,"fix",1470,1485,,-205.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-64,"fix",1485,1500,,-211.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-65,"fix",1500,1515,,-217.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-66,"fix",1515,1530,,-223.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-67,"fix",1530,1545,,-228.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-68,"fix",1545,1560,,-234.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-69,"fix",1560,1575,,-240.23,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-70,"fix",1575,1590,,-245.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-71,"fix",1590,1605,,-251.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-72,"fix",1605,1620,,-257.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-73,"fix",1620,1635,,-263.08,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-74,"fix",1635,1650,,-268.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-75,"fix",1650,1665,,-274.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-76,"fix",1665,1680,,-280.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-77,"fix",1680,1695,,-285.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-78,"fix",1695,1710,,-291.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-79,"fix",1710,1725,,-297.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-80,"fix",1725,1740,,-304.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-81,"fix",1740,1755,,-310.28,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-82,"fix",1755,1770,,-316.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-83,"fix",1770,1785,,-322.73,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-84,"fix",1785,1800,,-328.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-85,"fix",1800,1815,,-335.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-86,"fix",1815,1830,,-342.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-87,"fix",1830,1845,,-349.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-88,"fix",1845,1860,,-356.63,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-89,"fix",1860,1875,,-363.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-90,"fix",1875,1890,,-370.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-91,"fix",1890,1905,,-377.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-92,"fix",1905,1920,,-384.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-93,"fix",1920,1935,,-391.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-94,"fix",1935,1950,,-398.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-95,"fix",1950,1965,,-405.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-96,"fix",1965,1980,,-412.68,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-97,"fix",1980,1995,,-419.68,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-98,"fix",1995,2010,,-426.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-99,"fix",2010,2025,,-433.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-100,"fix",2025,2040,,-440.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-101,"fix",2040,2055,,-447.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-102,"fix",2055,2070,,-454.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-103,"fix",2070,2085,,-461.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-104,"fix",2085,2100,,-468.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-105,"fix",2100,2115,,-475.73,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-106,"fix",2115,2130,,-482.73,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-107,"fix",2130,2145,,-489.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-108,"fix",2145,2160,,-496.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-109,"fix",2160,2175,,-503.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-110,"fix",2175,2190,,-510.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-111,"fix",2190,2205,,-517.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-112,"fix",2205,2220,,-524.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-113,"fix",2220,2235,,-531.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-114,"fix",2235,2250,,-538.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-115,"fix",2250,2265,,-545.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-116,"fix",2265,2280,,-552.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-117,"fix",2280,2295,,-559.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-118,"fix",2295,2310,,-566.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-119,"fix",2310,2325,,-573.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-120,"fix",2325,2340,,-580.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-121,"fix",2340,2355,,-587.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-122,"fix",2355,2370,,-594.83,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-123,"fix",2370,2385,,-601.83,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-124,"fix",2385,2400,,-608.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-125,"fix",2400,2415,,-615.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-126,"fix",2415,2430,,-622.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-127,"fix",2430,2445,,-629.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-128,"fix",2445,2460,,-636.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-129,"fix",2460,2475,,-643.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-130,"fix",2475,2490,,-650.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-131,"fix",2490,2505,,-657.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-132,"fix",2505,2520,,-664.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-133,"fix",2520,2535,,-671.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-134,"fix",2535,2550,,-678.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-135,"fix",2550,2565,,-685.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-136,"fix",2565,2580,,-692.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-137,"fix",2580,2595,,-699.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-138,"fix",2595,2610,,-706.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-139,"fix",2610,2625,,-713.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-140,"fix",2625,2640,,-720.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-141,"fix",2640,2655,,-727.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-142,"fix",2655,2670,,-734.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-143,"fix",2670,2685,,-741.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-144,"fix",2685,2700,,-748.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-145,"fix",2700,2715,,-755.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-146,"fix",2715,2730,,-762.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-147,"fix",2730,2745,,-769.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-148,"fix",2745,2760,,-776.98,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-149,"fix",2760,2775,,-783.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-150,"fix",2775,2790,,-790.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-151,"fix",2790,2805,,-798.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-152,"fix",2805,2820,,-805.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-153,"fix",2820,2835,,-812.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-154,"fix",2835,2850,,-819.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-155,"fix",2850,2865,,-826.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-156,"fix",2865,2880,,-833.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-157,"fix",2880,2895,,-840.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-158,"fix",2895,2910,,-847.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-159,"fix",2910,2925,,-854.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-160,"fix",2925,2940,,-861.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-161,"fix",2940,2955,,-868.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-162,"fix",2955,2970,,-875.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-163,"fix",2970,2985,,-882.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-164,"fix",2985,3000,,-889.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-165,"fix",3000,3015,,-897.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-166,"fix",3015,3030,,-904.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-167,"fix",3030,3045,,-911.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-168,"fix",3045,3060,,-918.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-169,"fix",3060,3075,,-926.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-170,"fix",3075,3090,,-933.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-171,"fix",3090,3105,,-940.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-172,"fix",3105,3120,,-947.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-173,"fix",3120,3135,,-954.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-174,"fix",3135,3150,,-962.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-175,"fix",3150,3165,,-969.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-176,"fix",3165,3180,,-976.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-177,"fix",3180,3195,,-983.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-178,"fix",3195,3210,,-991.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-179,"fix",3210,3225,,-998.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-180,"fix",3225,3240,,-1005.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-181,"fix",3240,3255,,-1012.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-182,"fix",3255,3270,,-1019.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-183,"fix",3270,3285,,-1027.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-184,"fix",3285,3300,,-1034.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-185,"fix",3300,3315,,-1041.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-186,"fix",3315,3330,,-1048.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-187,"fix",3330,3345,,-1056.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-188,"fix",3345,3360,,-1063.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-189,"fix",3360,3375,,-1070.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-190,"fix",3375,3390,,-1077.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-191,"fix",3390,3405,,-1084.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-192,"fix",3405,3420,,-1092.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-193,"fix",3420,3435,,-1099.38,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-194,"fix",3435,3450,,-1106.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-195,"fix",3450,3465,,-1113.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-196,"fix",3465,3480,,-1121.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-197,"fix",3480,3495,,-1128.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-198,"fix",3495,3510,,-1135.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-199,"fix",3510,3525,,-1142.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-200,"fix",3525,3540,,-1149.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-201,"fix",3540,3555,,-1157.16,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-202,"fix",3555,3570,,-1164.38,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-203,"fix",3570,3585,,-1171.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-204,"fix",3585,3600,,-1178.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-205,"fix",3600,3615,,-1186.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-206,"fix",3615,3630,,-1194.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-207,"fix",3630,3645,,-1202.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-208,"fix",3645,3660,,-1210.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-209,"fix",3660,3675,,-1218.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-210,"fix",3675,3690,,-1226.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-211,"fix",3690,3705,,-1234.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-212,"fix",3705,3720,,-1242.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-213,"fix",3720,3735,,-1250.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-214,"fix",3735,3750,,-1258.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-215,"fix",3750,3765,,-1266.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-216,"fix",3765,3780,,-1274.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-217,"fix",3780,3795,,-1282.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-218,"fix",3795,3810,,-1290.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-219,"fix",3810,3825,,-1298.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-220,"fix",3825,3840,,-1306.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-221,"fix",3840,3855,,-1314.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-222,"fix",3855,3870,,-1322.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-223,"fix",3870,3885,,-1330.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-224,"fix",3885,3900,,-1338.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-225,"fix",3900,3915,,-1346.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-226,"fix",3915,3930,,-1354.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-227,"fix",3930,3945,,-1362.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-228,"fix",3945,3960,,-1370.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-229,"fix",3960,3975,,-1378.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-230,"fix",3975,3990,,-1386.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-231,"fix",3990,4005,,-1394.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-232,"fix",4005,4020,,-1402.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-233,"fix",4020,4035,,-1410.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-234,"fix",4035,4050,,-1418.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-235,"fix",4050,4065,,-1426.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-236,"fix",4065,4080,,-1435.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-237,"fix",4080,4095,,-1443.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-238,"fix",4095,4110,,-1451.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-239,"fix",4110,4125,,-1459.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-240,"fix",4125,4140,,-1467.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-241,"fix",4140,4155,,-1475.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-242,"fix",4155,4170,,-1483.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-243,"fix",4170,4185,,-1491.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-244,"fix",4185,4200,,-1499.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-245,"fix",4200,4215,,-1507.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-246,"fix",4215,4230,,-1515.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-247,"fix",4230,4245,,-1523.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-248,"fix",4245,4260,,-1531.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-249,"fix",4260,4275,,-1539.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-250,"fix",4275,4290,,-1547.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-251,"fix",4290,4305,,-1555.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-252,"fix",4305,4320,,-1563.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-253,"fix",4320,4335,,-1571.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-254,"fix",4335,4350,,-1579.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-255,"fix",4350,4365,,-1587.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-256,"fix",4365,4380,,-1595.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-257,"fix",4380,4395,,-1603.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-258,"fix",4395,4410,,-1611.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-259,"fix",4410,4425,,-1619.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-260,"fix",4425,4440,,-1627.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-261,"fix",4440,4455,,-1635.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-262,"fix",4455,4470,,-1643.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-263,"fix",4470,4485,,-1651.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-264,"fix",4485,4500,,-1659.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-265,"fix",4500,4515,,-1667.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-266,"fix",4515,4530,,-1675.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-267,"fix",4530,4545,,-1683.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-268,"fix",4545,4560,,-1691.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-269,"fix",4560,4575,,-1699.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-270,"fix",4575,4590,,-1707.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-271,"fix",4590,4605,,-1715.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-272,"fix",4605,4620,,-1723.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-273,"fix",4620,4635,,-1731.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-274,"fix",4635,4650,,-1739.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-275,"fix",4650,4665,,-1747.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-276,"fix",4665,4680,,-1756.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-277,"fix",4680,4695,,-1764.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-278,"fix",4695,4710,,-1772.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-279,"fix",4710,4725,,-1780.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-280,"fix",4725,4740,,-1788.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-281,"fix",4740,4755,,-1796.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-282,"fix",4755,4770,,-1804.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-283,"fix",4770,4785,,-1812.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-284,"fix",4785,4800,,-1820.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-285,"fix",4800,4815,,-1828.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-286,"fix",4815,4830,,-1836.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-287,"fix",4830,4845,,-1844.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-288,"fix",4845,4860,,-1852.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-289,"fix",4860,4875,,-1860.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-290,"fix",4875,4890,,-1868.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-291,"fix",4890,4905,,-1876.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-292,"fix",4905,4920,,-1884.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-293,"fix",4920,4935,,-1892.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-294,"fix",4935,4950,,-1900.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-295,"fix",4950,4965,,-1908.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-296,"fix",4965,4980,,-1916.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-297,"fix",4980,4995,,-1924.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-298,"fix",4995,5010,,-1932.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-299,"fix",5010,5025,,-1940.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-300,"fix",5025,5040,,-1948.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-301,"fix",5040,5055,,-1956.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-302,"fix",5055,5070,,-1964.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-303,"fix",5070,5085,,-1972.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-304,"fix",5085,5100,,-1980.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-305,"fix",5100,5115,,-1988.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-306,"fix",5115,5130,,-1996.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-307,"fix",5130,5145,,-2004.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-308,"fix",5145,5160,,-2012.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-309,"fix",5160,5175,,-2020.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-310,"fix",5175,5190,,-2028.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-311,"fix",5190,5205,,-2036.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-312,"fix",5205,5220,,-2044.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-313,"fix",5220,5235,,-2052.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-314,"fix",5235,5250,,-2060.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-315,"fix",5250,5265,,-2068.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-316,"fix",5265,5280,,-2077.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-317,"fix",5280,5295,,-2085.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-318,"fix",5295,5310,,-2093.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-319,"fix",5310,5325,,-2101.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-320,"fix",5325,5340,,-2109.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-321,"fix",5340,5355,,-2117.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-322,"fix",5355,5370,,-2125.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-323,"fix",5370,5385,,-2133.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-324,"fix",5385,5400,,-2141.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-325,"fix",5400,5415,,-2149.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-326,"fix",5415,5430,,-2157.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-327,"fix",5430,5445,,-2165.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-328,"fix",5445,5460,,-2173.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-329,"fix",5460,5475,,-2181.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-330,"fix",5475,5490,,-2189.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-331,"fix",5490,5505,,-2197.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-332,"fix",5505,5520,,-2205.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-333,"fix",5520,5535,,-2213.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-334,"fix",5535,5550,,-2221.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-335,"fix",5550,5565,,-2229.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-336,"fix",5565,5580,,-2237.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-337,"fix",5580,5595,,-2245.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-338,"fix",5595,5610,,-2253.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-339,"fix",5610,5625,,-2261.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-340,"fix",5625,5640,,-2269.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-341,"fix",5640,5655,,-2277.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-342,"fix",5655,5670,,-2285.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-343,"fix",5670,5685,,-2293.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-344,"fix",5685,5700,,-2301.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-345,"fix",5700,5715,,-2309.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-346,"fix",5715,5730,,-2317.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-347,"fix",5730,5745,,-2325.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-348,"fix",5745,5760,,-2333.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-349,"fix",5760,5775,,-2341.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-350,"fix",5775,5790,,-2349.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-351,"fix",5790,5805,,-2357.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-352,"fix",5805,5820,,-2365.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-353,"fix",5820,5835,,-2373.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-354,"fix",5835,5850,,-2381.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-355,"fix",5850,5865,,-2389.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-356,"fix",5865,5880,,-2398.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-357,"fix",5880,5895,,-2406.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-358,"fix",5895,5910,,-2414.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-359,"fix",5910,5925,,-2422.07, "Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-360,"fix",5925,5940,,-2430.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-361,"fix",5940,5955,,-2438.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-362,"fix",5955,5970,,-2446.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-363,"fix",5970,5985,,-2454.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-364,"fix",5985,6000,,-2462.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-365,"fix",6000,6015,,-2470.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-366,"fix",6015,6030,,-2478.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-367,"fix",6030,6045,,-2486.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-368,"fix",6045,6060,,-2494.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-369,"fix",6060,6075,,-2502.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-370,"fix",6075,6090,,-2510.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-371,"fix",6090,6105,,-2518.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-372,"fix",6105,6120,,-2526.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-373,"fix",6120,6135,,-2534.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-374,"fix",6135,6150,,-2542.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-375,"fix",6150,6165,,-2550.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-376,"fix",6165,6180,,-2558.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-377,"fix",6180,6195,,-2566.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-378,"fix",6195,6210,,-2574.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-379,"fix",6210,6225,,-2582.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-380,"fix",6225,6240,,-2590.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-381,"fix",6240,6255,,-2598.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-382,"fix",6255,6270,,-2606.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-383,"fix",6270,6285,,-2614.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-384,"fix",6285,6300,,-2622.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-385,"fix",6300,6315,,-2630.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-386,"fix",6315,6330,,-2638.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-387,"fix",6330,6345,,-2646.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-388,"fix",6345,6360,,-2654.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-389,"fix",6360,6375,,-2662.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-390,"fix",6375,6390,,-2670.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-391,"fix",6390,6405,,-2678.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-392,"fix",6405,6420,,-2686.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-393,"fix",6420,6435,,-2694.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-394,"fix",6435,6450,,-2702.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-395,"fix",6450,6465,,-2710.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-396,"fix",6465,6480,,-2719.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-397,"fix",6480,6495,,-2727.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-398,"fix",6495,6510,,-2735.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-399,"fix",6510,6525,,-2743.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-400,"fix",6525,6540,,-2751.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-401,"fix",6540,6555,,-2759.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-402,"fix",6555,6570,,-2767.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-403,"fix",6570,6585,,-2775.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-404,"fix",6585,6600,,-2783.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-405,"fix",6600,6615,,-2791.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-406,"fix",6615,6630,,-2799.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-407,"fix",6630,6645,,-2807.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-408,"fix",6645,6660,,-2815.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-409,"fix",6660,6675,,-2823.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-410,"fix",6675,6690,,-2831.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-411,"fix",6690,6705,,-2839.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-412,"fix",6705,6720,,-2847.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-413,"fix",6720,6735,,-2855.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-414,"fix",6735,6750,,-2863.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-415,"fix",6750,6765,,-2871.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-416,"fix",6765,6780,,-2879.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-417,"fix",6780,6795,,-2887.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-418,"fix",6795,6810,,-2895.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-419,"fix",6810,6825,,-2903.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-420,"fix",6825,6840,,-2911.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-421,"fix",6840,6855,,-2919.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-422,"fix",6855,6870,,-2927.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-423,"fix",6870,6885,,-2935.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-424,"fix",6885,6900,,-2943.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-425,"fix",6900,6915,,-2951.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-426,"fix",6915,6930,,-2959.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-427,"fix",6930,6945,,-2967.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-428,"fix",6945,6960,,-2975.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-429,"fix",6960,6975,,-2983.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-430,"fix",6975,6990,,-2991.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-431,"fix",6990,7005,,-2999.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-432,"fix",7005,7020,,-3007.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-433,"fix",7020,7035,,-3015.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-434,"fix",7035,7050,,-3023.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-435,"fix",7050,7065,,-3031.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-436,"fix",7065,7080,,-3040.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-437,"fix",7080,7095,,-3048.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-438,"fix",7095,7110,,-3056.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-439,"fix",7110,7125,,-3064.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-440,"fix",7125,7140,,-3072.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-441,"fix",7140,7155,,-3080.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-442,"fix",7155,7170,,-3088.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-443,"fix",7170,7185,,-3096.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-444,"fix",7185,7200,,-3104.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-445,"fix",7200,7215,,-3112.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-446,"fix",7215,7230,,-3120.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-447,"fix",7230,7245,,-3128.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-448,"fix",7245,7260,,-3136.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-449,"fix",7260,7275,,-3144.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-450,"fix",7275,7290,,-3152.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-451,"fix",7290,7305,,-3160.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-452,"fix",7305,7320,,-3168.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-453,"fix",7320,7335,,-3176.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-454,"fix",7335,7350,,-3184.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-455,"fix",7350,7365,,-3192.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-456,"fix",7365,7380,,-3200.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-457,"fix",7380,7395,,-3208.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-458,"fix",7395,7410,,-3216.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-459,"fix",7410,7425,,-2224.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-460,"fix",7425,7440,,-3232.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-461,"fix",7440,7455,,-3240.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-462,"fix",7455,7470,,-3248.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-463,"fix",7470,7485,,-3256.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-464,"fix",7485,7500,,-3264.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-465,"fix",7500,2147483647,,-3272.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+"id","amount_select","condition_range_min","condition_range_max","amount_percentage","amount_fix","amount_python_compute","name","category_id","sequence","code","parent_rule_id/id","condition_select","condition_range","amount_percentage_base","register_id/id"
+1,"fix",0,555,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+2,"fix",555,570,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+3,"fix",570,585,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+4,"fix",585,600,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+5,"fix",600,615,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+6,"fix",615,630,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+7,"fix",630,645,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+8,"fix",645,660,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+9,"fix",660,675,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+10,"fix",675,690,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+11,"fix",690,705,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+12,"fix",705,720,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+13,"fix",720,735,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+14,"fix",735,750,,-0.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+15,"fix",750,765,,-4.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+16,"fix",765,780,,-7.63,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+17,"fix",780,795,,-11.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+18,"fix",795,810,,-14.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+19,"fix",810,825,,-18.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+20,"fix",825,840,,-21.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+21,"fix",840,855,,-25.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+22,"fix",855,870,,-29.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+23,"fix",870,885,,-32.63,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+24,"fix",885,900,,-36.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+25,"fix",900,915,,-39.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+26,"fix",915,930,,-43.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+27,"fix",930,945,,-46.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+28,"fix",945,960,,-50.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+29,"fix",960,975,,-54.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+30,"fix",975,990,,-57.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+31,"fix",990,1005,,-61.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+32,"fix",1005,1020,,-64.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+33,"fix",1020,1035,,-68.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+34,"fix",1035,1050,,-71.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+35,"fix",1050,1065,,-75.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+36,"fix",1065,1080,,-79.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+37,"fix",1080,1095,,-82.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+38,"fix",1095,1110,,-86.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+39,"fix",1110,1125,,-89.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+40,"fix",1125,1140,,-93.33,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+41,"fix",1140,1155,,-96.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+42,"fix",1155,1170,,-100.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+43,"fix",1170,1185,,-104.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+44,"fix",1185,1200,,-107.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+45,"fix",1200,1215,,-111.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+46,"fix",1215,1230,,-115.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+47,"fix",1230,1245,,-120.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+48,"fix",1245,1260,,-124.53,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+49,"fix",1260,1275,,-128.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+50,"fix",1275,1290,,-133.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+51,"fix",1290,1305,,-137.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+52,"fix",1305,1320,,-143.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+53,"fix",1320,1335,,-148.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+54,"fix",1335,1350,,-154.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+55,"fix",1350,1365,,-160.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+56,"fix",1365,1380,,-165.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+57,"fix",1380,1395,,-171.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+58,"fix",1395,1410,,-177.38,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+59,"fix",1410,1425,,-183.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+60,"fix",1425,1440,,-188.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+61,"fix",1440,1455,,-194.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+62,"fix",1455,1470,,-200.23,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+63,"fix",1470,1485,,-205.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+64,"fix",1485,1500,,-211.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+65,"fix",1500,1515,,-217.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+66,"fix",1515,1530,,-223.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+67,"fix",1530,1545,,-228.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+68,"fix",1545,1560,,-234.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+69,"fix",1560,1575,,-240.23,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+70,"fix",1575,1590,,-245.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+71,"fix",1590,1605,,-251.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+72,"fix",1605,1620,,-257.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+73,"fix",1620,1635,,-263.08,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+74,"fix",1635,1650,,-268.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+75,"fix",1650,1665,,-274.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+76,"fix",1665,1680,,-280.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+77,"fix",1680,1695,,-285.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+78,"fix",1695,1710,,-291.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+79,"fix",1710,1725,,-297.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+80,"fix",1725,1740,,-304.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+81,"fix",1740,1755,,-310.28,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+82,"fix",1755,1770,,-316.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+83,"fix",1770,1785,,-322.73,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+84,"fix",1785,1800,,-328.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+85,"fix",1800,1815,,-335.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+86,"fix",1815,1830,,-342.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+87,"fix",1830,1845,,-349.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+88,"fix",1845,1860,,-356.63,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+89,"fix",1860,1875,,-363.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+90,"fix",1875,1890,,-370.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+91,"fix",1890,1905,,-377.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+92,"fix",1905,1920,,-384.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+93,"fix",1920,1935,,-391.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+94,"fix",1935,1950,,-398.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+95,"fix",1950,1965,,-405.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+96,"fix",1965,1980,,-412.68,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+97,"fix",1980,1995,,-419.68,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+98,"fix",1995,2010,,-426.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+99,"fix",2010,2025,,-433.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+100,"fix",2025,2040,,-440.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+101,"fix",2040,2055,,-447.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+102,"fix",2055,2070,,-454.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+103,"fix",2070,2085,,-461.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+104,"fix",2085,2100,,-468.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+105,"fix",2100,2115,,-475.73,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+106,"fix",2115,2130,,-482.73,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+107,"fix",2130,2145,,-489.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+108,"fix",2145,2160,,-496.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+109,"fix",2160,2175,,-503.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+110,"fix",2175,2190,,-510.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+111,"fix",2190,2205,,-517.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+112,"fix",2205,2220,,-524.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+113,"fix",2220,2235,,-531.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+114,"fix",2235,2250,,-538.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+115,"fix",2250,2265,,-545.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+116,"fix",2265,2280,,-552.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+117,"fix",2280,2295,,-559.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+118,"fix",2295,2310,,-566.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+119,"fix",2310,2325,,-573.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+120,"fix",2325,2340,,-580.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+121,"fix",2340,2355,,-587.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+122,"fix",2355,2370,,-594.83,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+123,"fix",2370,2385,,-601.83,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+124,"fix",2385,2400,,-608.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+125,"fix",2400,2415,,-615.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+126,"fix",2415,2430,,-622.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+127,"fix",2430,2445,,-629.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+128,"fix",2445,2460,,-636.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+129,"fix",2460,2475,,-643.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+130,"fix",2475,2490,,-650.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+131,"fix",2490,2505,,-657.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+132,"fix",2505,2520,,-664.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+133,"fix",2520,2535,,-671.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+134,"fix",2535,2550,,-678.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+135,"fix",2550,2565,,-685.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+136,"fix",2565,2580,,-692.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+137,"fix",2580,2595,,-699.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+138,"fix",2595,2610,,-706.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+139,"fix",2610,2625,,-713.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+140,"fix",2625,2640,,-720.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+141,"fix",2640,2655,,-727.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+142,"fix",2655,2670,,-734.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+143,"fix",2670,2685,,-741.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+144,"fix",2685,2700,,-748.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+145,"fix",2700,2715,,-755.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+146,"fix",2715,2730,,-762.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+147,"fix",2730,2745,,-769.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+148,"fix",2745,2760,,-776.98,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+149,"fix",2760,2775,,-783.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+150,"fix",2775,2790,,-790.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+151,"fix",2790,2805,,-798.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+152,"fix",2805,2820,,-805.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+153,"fix",2820,2835,,-812.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+154,"fix",2835,2850,,-819.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+155,"fix",2850,2865,,-826.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+156,"fix",2865,2880,,-833.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+157,"fix",2880,2895,,-840.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+158,"fix",2895,2910,,-847.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+159,"fix",2910,2925,,-854.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+160,"fix",2925,2940,,-861.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+161,"fix",2940,2955,,-868.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+162,"fix",2955,2970,,-875.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+163,"fix",2970,2985,,-882.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+164,"fix",2985,3000,,-889.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+165,"fix",3000,3015,,-897.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+166,"fix",3015,3030,,-904.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+167,"fix",3030,3045,,-911.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+168,"fix",3045,3060,,-918.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+169,"fix",3060,3075,,-926.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+170,"fix",3075,3090,,-933.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+171,"fix",3090,3105,,-940.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+172,"fix",3105,3120,,-947.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+173,"fix",3120,3135,,-954.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+174,"fix",3135,3150,,-962.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+175,"fix",3150,3165,,-969.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+176,"fix",3165,3180,,-976.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+177,"fix",3180,3195,,-983.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+178,"fix",3195,3210,,-991.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+179,"fix",3210,3225,,-998.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+180,"fix",3225,3240,,-1005.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+181,"fix",3240,3255,,-1012.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+182,"fix",3255,3270,,-1019.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+183,"fix",3270,3285,,-1027.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+184,"fix",3285,3300,,-1034.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+185,"fix",3300,3315,,-1041.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+186,"fix",3315,3330,,-1048.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+187,"fix",3330,3345,,-1056.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+188,"fix",3345,3360,,-1063.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+189,"fix",3360,3375,,-1070.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+190,"fix",3375,3390,,-1077.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+191,"fix",3390,3405,,-1084.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+192,"fix",3405,3420,,-1092.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+193,"fix",3420,3435,,-1099.38,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+194,"fix",3435,3450,,-1106.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+195,"fix",3450,3465,,-1113.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+196,"fix",3465,3480,,-1121.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+197,"fix",3480,3495,,-1128.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+198,"fix",3495,3510,,-1135.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+199,"fix",3510,3525,,-1142.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+200,"fix",3525,3540,,-1149.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+201,"fix",3540,3555,,-1157.16,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+202,"fix",3555,3570,,-1164.38,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+203,"fix",3570,3585,,-1171.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+204,"fix",3585,3600,,-1178.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+205,"fix",3600,3615,,-1186.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+206,"fix",3615,3630,,-1194.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+207,"fix",3630,3645,,-1202.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+208,"fix",3645,3660,,-1210.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+209,"fix",3660,3675,,-1218.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+210,"fix",3675,3690,,-1226.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+211,"fix",3690,3705,,-1234.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+212,"fix",3705,3720,,-1242.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+213,"fix",3720,3735,,-1250.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+214,"fix",3735,3750,,-1258.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+215,"fix",3750,3765,,-1266.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+216,"fix",3765,3780,,-1274.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+217,"fix",3780,3795,,-1282.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+218,"fix",3795,3810,,-1290.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+219,"fix",3810,3825,,-1298.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+220,"fix",3825,3840,,-1306.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+221,"fix",3840,3855,,-1314.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+222,"fix",3855,3870,,-1322.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+223,"fix",3870,3885,,-1330.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+224,"fix",3885,3900,,-1338.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+225,"fix",3900,3915,,-1346.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+226,"fix",3915,3930,,-1354.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+227,"fix",3930,3945,,-1362.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+228,"fix",3945,3960,,-1370.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+229,"fix",3960,3975,,-1378.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+230,"fix",3975,3990,,-1386.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+231,"fix",3990,4005,,-1394.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+232,"fix",4005,4020,,-1402.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+233,"fix",4020,4035,,-1410.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+234,"fix",4035,4050,,-1418.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+235,"fix",4050,4065,,-1426.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+236,"fix",4065,4080,,-1435.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+237,"fix",4080,4095,,-1443.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+238,"fix",4095,4110,,-1451.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+239,"fix",4110,4125,,-1459.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+240,"fix",4125,4140,,-1467.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+241,"fix",4140,4155,,-1475.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+242,"fix",4155,4170,,-1483.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+243,"fix",4170,4185,,-1491.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+244,"fix",4185,4200,,-1499.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+245,"fix",4200,4215,,-1507.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+246,"fix",4215,4230,,-1515.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+247,"fix",4230,4245,,-1523.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+248,"fix",4245,4260,,-1531.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+249,"fix",4260,4275,,-1539.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+250,"fix",4275,4290,,-1547.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+251,"fix",4290,4305,,-1555.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+252,"fix",4305,4320,,-1563.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+253,"fix",4320,4335,,-1571.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+254,"fix",4335,4350,,-1579.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+255,"fix",4350,4365,,-1587.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+256,"fix",4365,4380,,-1595.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+257,"fix",4380,4395,,-1603.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+258,"fix",4395,4410,,-1611.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+259,"fix",4410,4425,,-1619.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+260,"fix",4425,4440,,-1627.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+261,"fix",4440,4455,,-1635.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+262,"fix",4455,4470,,-1643.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+263,"fix",4470,4485,,-1651.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+264,"fix",4485,4500,,-1659.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+265,"fix",4500,4515,,-1667.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+266,"fix",4515,4530,,-1675.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+267,"fix",4530,4545,,-1683.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+268,"fix",4545,4560,,-1691.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+269,"fix",4560,4575,,-1699.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+270,"fix",4575,4590,,-1707.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+271,"fix",4590,4605,,-1715.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+272,"fix",4605,4620,,-1723.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+273,"fix",4620,4635,,-1731.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+274,"fix",4635,4650,,-1739.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+275,"fix",4650,4665,,-1747.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+276,"fix",4665,4680,,-1756.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+277,"fix",4680,4695,,-1764.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+278,"fix",4695,4710,,-1772.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+279,"fix",4710,4725,,-1780.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+280,"fix",4725,4740,,-1788.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+281,"fix",4740,4755,,-1796.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+282,"fix",4755,4770,,-1804.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+283,"fix",4770,4785,,-1812.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+284,"fix",4785,4800,,-1820.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+285,"fix",4800,4815,,-1828.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+286,"fix",4815,4830,,-1836.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+287,"fix",4830,4845,,-1844.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+288,"fix",4845,4860,,-1852.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+289,"fix",4860,4875,,-1860.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+290,"fix",4875,4890,,-1868.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+291,"fix",4890,4905,,-1876.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+292,"fix",4905,4920,,-1884.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+293,"fix",4920,4935,,-1892.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+294,"fix",4935,4950,,-1900.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+295,"fix",4950,4965,,-1908.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+296,"fix",4965,4980,,-1916.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+297,"fix",4980,4995,,-1924.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+298,"fix",4995,5010,,-1932.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+299,"fix",5010,5025,,-1940.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+300,"fix",5025,5040,,-1948.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+301,"fix",5040,5055,,-1956.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+302,"fix",5055,5070,,-1964.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+303,"fix",5070,5085,,-1972.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+304,"fix",5085,5100,,-1980.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+305,"fix",5100,5115,,-1988.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+306,"fix",5115,5130,,-1996.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+307,"fix",5130,5145,,-2004.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+308,"fix",5145,5160,,-2012.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+309,"fix",5160,5175,,-2020.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+310,"fix",5175,5190,,-2028.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+311,"fix",5190,5205,,-2036.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+312,"fix",5205,5220,,-2044.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+313,"fix",5220,5235,,-2052.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+314,"fix",5235,5250,,-2060.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+315,"fix",5250,5265,,-2068.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+316,"fix",5265,5280,,-2077.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+317,"fix",5280,5295,,-2085.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+318,"fix",5295,5310,,-2093.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+319,"fix",5310,5325,,-2101.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+320,"fix",5325,5340,,-2109.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+321,"fix",5340,5355,,-2117.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+322,"fix",5355,5370,,-2125.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+323,"fix",5370,5385,,-2133.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+324,"fix",5385,5400,,-2141.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+325,"fix",5400,5415,,-2149.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+326,"fix",5415,5430,,-2157.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+327,"fix",5430,5445,,-2165.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+328,"fix",5445,5460,,-2173.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+329,"fix",5460,5475,,-2181.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+330,"fix",5475,5490,,-2189.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+331,"fix",5490,5505,,-2197.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+332,"fix",5505,5520,,-2205.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+333,"fix",5520,5535,,-2213.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+334,"fix",5535,5550,,-2221.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+335,"fix",5550,5565,,-2229.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+336,"fix",5565,5580,,-2237.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+337,"fix",5580,5595,,-2245.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+338,"fix",5595,5610,,-2253.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+339,"fix",5610,5625,,-2261.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+340,"fix",5625,5640,,-2269.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+341,"fix",5640,5655,,-2277.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+342,"fix",5655,5670,,-2285.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+343,"fix",5670,5685,,-2293.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+344,"fix",5685,5700,,-2301.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+345,"fix",5700,5715,,-2309.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+346,"fix",5715,5730,,-2317.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+347,"fix",5730,5745,,-2325.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+348,"fix",5745,5760,,-2333.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+349,"fix",5760,5775,,-2341.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+350,"fix",5775,5790,,-2349.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+351,"fix",5790,5805,,-2357.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+352,"fix",5805,5820,,-2365.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+353,"fix",5820,5835,,-2373.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+354,"fix",5835,5850,,-2381.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+355,"fix",5850,5865,,-2389.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+356,"fix",5865,5880,,-2398.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+357,"fix",5880,5895,,-2406.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+358,"fix",5895,5910,,-2414.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+359,"fix",5910,5925,,-2422.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+360,"fix",5925,5940,,-2430.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+361,"fix",5940,5955,,-2438.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+362,"fix",5955,5970,,-2446.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+363,"fix",5970,5985,,-2454.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+364,"fix",5985,6000,,-2462.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+365,"fix",6000,6015,,-2470.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+366,"fix",6015,6030,,-2478.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+367,"fix",6030,6045,,-2486.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+368,"fix",6045,6060,,-2494.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+369,"fix",6060,6075,,-2502.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+370,"fix",6075,6090,,-2510.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+371,"fix",6090,6105,,-2518.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+372,"fix",6105,6120,,-2526.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+373,"fix",6120,6135,,-2534.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+374,"fix",6135,6150,,-2542.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+375,"fix",6150,6165,,-2550.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+376,"fix",6165,6180,,-2558.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+377,"fix",6180,6195,,-2566.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+378,"fix",6195,6210,,-2574.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+379,"fix",6210,6225,,-2582.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+380,"fix",6225,6240,,-2590.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+381,"fix",6240,6255,,-2598.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+382,"fix",6255,6270,,-2606.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+383,"fix",6270,6285,,-2614.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+384,"fix",6285,6300,,-2622.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+385,"fix",6300,6315,,-2630.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+386,"fix",6315,6330,,-2638.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+387,"fix",6330,6345,,-2646.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+388,"fix",6345,6360,,-2654.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+389,"fix",6360,6375,,-2662.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+390,"fix",6375,6390,,-2670.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+391,"fix",6390,6405,,-2678.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+392,"fix",6405,6420,,-2686.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+393,"fix",6420,6435,,-2694.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+394,"fix",6435,6450,,-2702.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+395,"fix",6450,6465,,-2710.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+396,"fix",6465,6480,,-2719.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+397,"fix",6480,6495,,-2727.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+398,"fix",6495,6510,,-2735.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+399,"fix",6510,6525,,-2743.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+400,"fix",6525,6540,,-2751.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+401,"fix",6540,6555,,-2759.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+402,"fix",6555,6570,,-2767.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+403,"fix",6570,6585,,-2775.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+404,"fix",6585,6600,,-2783.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+405,"fix",6600,6615,,-2791.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+406,"fix",6615,6630,,-2799.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+407,"fix",6630,6645,,-2807.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+408,"fix",6645,6660,,-2815.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+409,"fix",6660,6675,,-2823.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+410,"fix",6675,6690,,-2831.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+411,"fix",6690,6705,,-2839.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+412,"fix",6705,6720,,-2847.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+413,"fix",6720,6735,,-2855.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+414,"fix",6735,6750,,-2863.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+415,"fix",6750,6765,,-2871.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+416,"fix",6765,6780,,-2879.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+417,"fix",6780,6795,,-2887.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+418,"fix",6795,6810,,-2895.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+419,"fix",6810,6825,,-2903.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+420,"fix",6825,6840,,-2911.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+421,"fix",6840,6855,,-2919.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+422,"fix",6855,6870,,-2927.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+423,"fix",6870,6885,,-2935.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+424,"fix",6885,6900,,-2943.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+425,"fix",6900,6915,,-2951.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+426,"fix",6915,6930,,-2959.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+427,"fix",6930,6945,,-2967.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+428,"fix",6945,6960,,-2975.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+429,"fix",6960,6975,,-2983.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+430,"fix",6975,6990,,-2991.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+431,"fix",6990,7005,,-2999.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+432,"fix",7005,7020,,-3007.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+433,"fix",7020,7035,,-3015.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+434,"fix",7035,7050,,-3023.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+435,"fix",7050,7065,,-3031.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+436,"fix",7065,7080,,-3040.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+437,"fix",7080,7095,,-3048.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+438,"fix",7095,7110,,-3056.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+439,"fix",7110,7125,,-3064.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+440,"fix",7125,7140,,-3072.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+441,"fix",7140,7155,,-3080.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+442,"fix",7155,7170,,-3088.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+443,"fix",7170,7185,,-3096.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+444,"fix",7185,7200,,-3104.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+445,"fix",7200,7215,,-3112.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+446,"fix",7215,7230,,-3120.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+447,"fix",7230,7245,,-3128.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+448,"fix",7245,7260,,-3136.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+449,"fix",7260,7275,,-3144.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+450,"fix",7275,7290,,-3152.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+451,"fix",7290,7305,,-3160.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+452,"fix",7305,7320,,-3168.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+453,"fix",7320,7335,,-3176.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+454,"fix",7335,7350,,-3184.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+455,"fix",7350,7365,,-3192.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+456,"fix",7365,7380,,-3200.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+457,"fix",7380,7395,,-3208.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+458,"fix",7395,7410,,-3216.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+459,"fix",7410,7425,,-2224.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+460,"fix",7425,7440,,-3232.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+461,"fix",7440,7455,,-3240.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+462,"fix",7455,7470,,-3248.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+463,"fix",7470,7485,,-3256.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+464,"fix",7485,7500,,-3264.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
+465,"fix",7500,2147483647,,-3272.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_bareme","range","GROSS",,"contrib_register_pp"
-,,,,,,,,,,,,,,
-600,"fix",0,1065,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-601,"fix",1065,1080,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-602,"fix",1080,1095,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-603,"fix",1095,1110,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-604,"fix",1110,1125,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-605,"fix",1125,1140,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-606,"fix",1140,1155,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-607,"fix",1155,1170,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-608,"fix",1170,1185,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-609,"fix",1185,1200,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-610,"fix",1200,1215,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-611,"fix",1215,1230,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-612,"fix",1230,1245,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-613,"fix",1245,1260,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-614,"fix",1260,1275,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-615,"fix",1275,1290,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-616,"fix",1290,1305,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-617,"fix",1305,1320,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-618,"fix",1320,1335,,-1.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-619,"fix",1335,1350,,-5.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-620,"fix",1350,1365,,-8.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-621,"fix",1365,1380,,-12.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-622,"fix",1380,1395,,-16.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-623,"fix",1395,1410,,-19.63,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-624,"fix",1410,1425,,-23.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-625,"fix",1425,1440,,-26.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-626,"fix",1440,1455,,-30.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-627,"fix",1455,1470,,-33.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-628,"fix",1470,1485,,-37.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-629,"fix",1485,1500,,-41.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-630,"fix",1500,1515,,-44.63,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-631,"fix",1515,1530,,-48.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-632,"fix",1530,1545,,-51.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-633,"fix",1545,1560,,-55.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-634,"fix",1560,1575,,-58.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-635,"fix",1575,1590,,-62.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-636,"fix",1590,1605,,-66.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-637,"fix",1605,1620,,-69.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-638,"fix",1620,1635,,-73.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-639,"fix",1635,1650,,-76.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-640,"fix",1650,1665,,-80.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-641,"fix",1665,1680,,-84.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-642,"fix",1680,1695,,-89.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-643,"fix",1695,1710,,-93.08,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-644,"fix",1710,1725,,-97.48,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-645,"fix",1725,1740,,-101.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-646,"fix",1740,1755,,-106.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-647,"fix",1755,1770,,-110.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-648,"fix",1770,1785,,-115.23,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-649,"fix",1785,1800,,-120.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-650,"fix",1800,1815,,-126.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-651,"fix",1815,1830,,-131.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-652,"fix",1830,1845,,-137.29,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-653,"fix",1845,1860,,-142.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-654,"fix",1860,1875,,-148.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-655,"fix",1875,1890,,-153.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-656,"fix",1890,1905,,-159.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-657,"fix",1905,1920,,-164.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-658,"fix",1920,1935,,-170.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-659,"fix",1935,1950,,-175.98,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-660,"fix",1950,1965,,-181.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-661,"fix",1965,1980,,-187.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-662,"fix",1980,1995,,-192.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-663,"fix",1995,2010,,-198.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-664,"fix",2010,2025,,-203.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-665,"fix",2025,2040,,-209.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-666,"fix",2040,2055,,-214.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-667,"fix",2055,2070,,-220.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-668,"fix",2070,2085,,-225.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-669,"fix",2085,2100,,-231.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-670,"fix",2100,2115,,-236.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-671,"fix",2115,2130,,-242.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-672,"fix",2130,2145,,-247.83,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-673,"fix",2145,2160,,-253.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-674,"fix",2160,2175,,-258.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-675,"fix",2175,2190,,-264.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-676,"fix",2190,2205,,-269.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-677,"fix",2205,2220,,-275.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-678,"fix",2220,2235,,-280.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-679,"fix",2235,2250,,-286.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-680,"fix",2250,2265,,-292.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-681,"fix",2265,2280,,-297.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-682,"fix",2280,2295,,-303.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-683,"fix",2295,2310,,-308.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-684,"fix",2310,2325,,-314.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-685,"fix",2325,2340,,-319.68,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-686,"fix",2340,2355,,-325.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-687,"fix",2355,2370,,-330.73,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-688,"fix",2370,2385,,-336.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-689,"fix",2385,2400,,-341.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-690,"fix",2400,2415,,-347.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-691,"fix",2415,2430,,-352.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-692,"fix",2430,2445,,-358.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-693,"fix",2445,2460,,-364.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-694,"fix",2460,2475,,-370.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-695,"fix",2475,2490,,-376.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-696,"fix",2490,2505,,-382.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-697,"fix",2505,2520,,-388.38,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-698,"fix",2520,2535,,-394.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-699,"fix",2535,2550,,-400.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-700,"fix",2550,2565,,-406.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-701,"fix",2565,2580,,-412.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-702,"fix",2580,2595,,-418.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-703,"fix",2595,2610,,-424.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-704,"fix",2610,2625,,-430.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-705,"fix",2625,2640,,-436.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-706,"fix",2640,2655,,-443.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-707,"fix",2655,2670,,-449.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-708,"fix",2670,2685,,-455.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-709,"fix",2685,2700,,-461.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-710,"fix",2700,2715,,-467.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-711,"fix",2715,2730,,-473.38,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-712,"fix",2730,2745,,-479.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-713,"fix",2745,2760,,-485.53,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-714,"fix",2760,2775,,-491.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-715,"fix",2775,2790,,-497.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-716,"fix",2790,2805,,-503.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-717,"fix",2805,2820,,-509.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-718,"fix",2820,2835,,-515.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-719,"fix",2835,2850,,-521.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-720,"fix",2850,2865,,-528.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-721,"fix",2865,2880,,-534.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-722,"fix",2880,2895,,-540.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-723,"fix",2895,2910,,-546.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-724,"fix",2910,2925,,-552.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-725,"fix",2925,2940,,-558.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-726,"fix",2940,2955,,-564.63,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-727,"fix",2955,2970,,-570.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-728,"fix",2970,2985,,-577.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-729,"fix",2985,3000,,-583.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-730,"fix",3000,3015,,-589.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-731,"fix",3015,3030,,-595.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-732,"fix",3030,3045,,-602.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-733,"fix",3045,3060,,-608.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-734,"fix",3060,3075,,-614.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-735,"fix",3075,3090,,-620.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-736,"fix",3090,3105,,-627.23,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-737,"fix",3105,3120,,-633.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-738,"fix",3120,3135,,-639.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-739,"fix",3135,3150,,-646.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-740,"fix",3150,3165,,-652.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-741,"fix",3165,3180,,-658.53,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-742,"fix",3180,3195,,-664.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-743,"fix",3195,3210,,-671.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-744,"fix",3210,3225,,-677.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-745,"fix",3225,3240,,-683.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-746,"fix",3240,3255,,-689.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-747,"fix",3255,3270,,-696.08,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-748,"fix",3270,3285,,-702.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-749,"fix",3285,3300,,-709.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-750,"fix",3300,3315,,-716.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-751,"fix",3315,3330,,-723.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-752,"fix",3330,3345,,-730.98,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-753,"fix",3345,3360,,-738.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-754,"fix",3360,3375,,-745.43,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-755,"fix",3375,3390,,-752.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-756,"fix",3390,3405,,-759.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-757,"fix",3405,3420,,-767.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-758,"fix",3420,3435,,-774.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-759,"fix",3435,3450,,-781.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-760,"fix",3450,3465,,-788.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-761,"fix",3465,3480,,-795.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-762,"fix",3480,3495,,-803.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-763,"fix",3495,3510,,-810.43,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-764,"fix",3510,3525,,-817.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-765,"fix",3525,3540,,-824.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-766,"fix",3540,3555,,-832.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-767,"fix",3555,3570,,-839.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-768,"fix",3570,3585,,-846.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-769,"fix",3585,3600,,-853.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-770,"fix",3600,3615,,-860.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-771,"fix",3615,3630,,-868.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-772,"fix",3630,3645,,-875.43,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-773,"fix",3645,3660,,-882.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-774,"fix",3660,3675,,-889.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-775,"fix",3675,3690,,-897.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-776,"fix",3690,3705,,-904.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-777,"fix",3705,3720,,-911.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-778,"fix",3720,3735,,-918.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-779,"fix",3735,3750,,-925.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-780,"fix",3750,3765,,-933.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-781,"fix",3765,3780,,-940.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-782,"fix",3780,3795,,-947.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-783,"fix",3795,3810,,-954.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-784,"fix",3810,3825,,-962.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-785,"fix",3825,3840,,-969.33,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-786,"fix",3840,3855,,-976.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-787,"fix",3855,3870,,-983.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-788,"fix",3870,3885,,-990.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-789,"fix",3885,3900,,-998.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-790,"fix",3900,3915,,-1005.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-791,"fix",3915,3930,,-1012.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-792,"fix",3930,3945,,-1019.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-793,"fix",3945,3960,,-1027.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-794,"fix",3960,3975,,-1034.33,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-795,"fix",3975,3990,,-1041.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-796,"fix",3990,4005,,-1048.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-797,"fix",4005,4020,,-1056.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-798,"fix",4020,4035,,-1063.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-799,"fix",4035,4050,,-1070.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-800,"fix",4050,4065,,-1077.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-801,"fix",4065,4080,,-1084.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-802,"fix",4080,4095,,-1092.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-803,"fix",4095,4110,,-1099.33,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-804,"fix",4110,4125,,-1106.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-805,"fix",4125,4140,,-1113.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-806,"fix",4140,4155,,-1121.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-807,"fix",4155,4170,,-1128.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-808,"fix",4170,4185,,-1135.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-809,"fix",4185,4200,,-1142.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-810,"fix",4200,4215,,-1149.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-811,"fix",4215,4230,,-1157.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-812,"fix",4230,4245,,-1164.33,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-813,"fix",4245,4260,,-1171.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-814,"fix",4260,4275,,-1178.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-815,"fix",4275,4290,,-1186.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-816,"fix",4290,4305,,-1193.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-817,"fix",4305,4320,,-1200.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-818,"fix",4320,4335,,-1207.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-819,"fix",4335,4350,,-1214.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-820,"fix",4350,4365,,-1222.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-821,"fix",4365,4380,,-1229.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-822,"fix",4380,4395,,-1236.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-823,"fix",4395,4410,,-1243.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-824,"fix",4410,4425,,-1251.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-825,"fix",4425,4440,,-1258.23,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-826,"fix",4440,4455,,-1265.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-827,"fix",4455,4470,,-1272.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-828,"fix",4470,4485,,-1279.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-829,"fix",4485,4500,,-1287.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-830,"fix",4500,4515,,-1295.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-831,"fix",4515,4530,,-1303.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-832,"fix",4530,4545,,-1311.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-833,"fix",4545,4560,,-1319.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-834,"fix",4560,4575,,-1328.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-835,"fix",4575,4590,,-1336.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-836,"fix",4590,4605,,-1344.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-837,"fix",4605,4620,,-1352.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-838,"fix",4620,4635,,-1360.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-839,"fix",4635,4650,,-1368.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-840,"fix",4650,4665,,-1376.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-841,"fix",4665,4680,,-1384.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-842,"fix",4680,4695,,-1392.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-843,"fix",4695,4710,,-1400.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-844,"fix",4710,4725,,-1408.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-845,"fix",4725,4740,,-1416.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-846,"fix",4740,4755,,-1424.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-847,"fix",4755,4770,,-1432.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-848,"fix",4770,4785,,-1440.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-849,"fix",4785,4800,,-1448.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-850,"fix",4800,4815,,-1456.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-851,"fix",4815,4830,,-1464.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-852,"fix",4830,4845,,-1472.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-853,"fix",4845,4860,,-1480.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-854,"fix",4860,4875,,-1488.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-855,"fix",4875,4890,,-1496.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-856,"fix",4890,4905,,-1504.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-857,"fix",4905,4920,,-1512.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-858,"fix",4920,4935,,-1520.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-859,"fix",4935,4950,,-1528.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-860,"fix",4950,4965,,-1536.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-861,"fix",4965,4980,,-1544.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-862,"fix",4980,4995,,-1552.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-863,"fix",4995,5010,,-1560.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-864,"fix",5010,5025,,-1568.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-865,"fix",5025,5040,,-1576.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-866,"fix",5040,5055,,-1584.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-867,"fix",5055,5070,,-1592.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-868,"fix",5070,5085,,-1600.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-869,"fix",5085,5100,,-1608.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-870,"fix",5100,5115,,-1616.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-871,"fix",5115,5130,,-1624.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-872,"fix",5130,5145,,-1632.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-873,"fix",5145,5160,,-1640.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-874,"fix",5160,5175,,-1649.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-875,"fix",5175,5190,,-1657.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-876,"fix",5190,5205,,-1665.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-877,"fix",5205,5220,,-1673.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-878,"fix",5220,5235,,-1681.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-879,"fix",5235,5250,,-1689.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-880,"fix",5250,5265,,-1697.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-881,"fix",5265,5280,,-1705.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-882,"fix",5280,5295,,-1713.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-883,"fix",5295,5310,,-1721.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-884,"fix",5310,5325,,-1729.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-885,"fix",5325,5340,,-1737.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-886,"fix",5340,5355,,-1745.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-887,"fix",5355,5370,,-1753.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-888,"fix",5370,5385,,-1761.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-889,"fix",5385,5400,,-1769.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-890,"fix",5400,5415,,-1777.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-891,"fix",5415,5430,,-1785.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-892,"fix",5430,5445,,-1793.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-893,"fix",5445,5460,,-1801.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-894,"fix",5460,5475,,-1809.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-895,"fix",5475,5490,,-1817.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-896,"fix",5490,5505,,-1825.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-897,"fix",5505,5520,,-1833.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-898,"fix",5520,5535,,-1841.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-899,"fix",5535,5550,,-1849.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-900,"fix",5550,5565,,-1857.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-901,"fix",5565,5580,,-1865.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-902,"fix",5580,5595,,-1873.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-903,"fix",5595,5610,,-1881.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-904,"fix",5610,5625,,-1889.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-905,"fix",5625,5640,,-1897.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-906,"fix",5640,5655,,-1905.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-907,"fix",5655,5670,,-1913.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-908,"fix",5670,5685,,-1921.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-909,"fix",5685,5700,,-1929.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-910,"fix",5700,5715,,-1937.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-911,"fix",5715,5730,,-1945.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-912,"fix",5730,5745,,-1953.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-913,"fix",5745,5760,,-1961.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-914,"fix",5760,5775,,-1970.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-915,"fix",5775,5790,,-1978.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-916,"fix",5790,5805,,-1986.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-917,"fix",5805,5820,,-1994.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-918,"fix",5820,5835,,-2002.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-919,"fix",5835,5850,,-2010.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-920,"fix",5850,5865,,-2018.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-921,"fix",5865,5880,,-2026.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-922,"fix",5880,5895,,-2034.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-923,"fix",5895,5910,,-2042.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-924,"fix",5910,5925,,-2050.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-925,"fix",5925,5940,,-2058.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-926,"fix",5940,5955,,-2066.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-927,"fix",5955,5970,,-2074.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-928,"fix",5970,5985,,-2082.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-929,"fix",5985,6000,,-2090.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-930,"fix",6000,6015,,-2098.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-931,"fix",6015,6030,,-2106.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-932,"fix",6030,6045,,-2114.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-933,"fix",6045,6060,,-2122.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-934,"fix",6060,6075,,-2130.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-935,"fix",6075,6090,,-2138.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-936,"fix",6090,6105,,-2146.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-937,"fix",6105,6120,,-2154.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-938,"fix",6120,6135,,-2162.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-939,"fix",6135,6150,,-2170.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-940,"fix",6150,6165,,-2178.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-941,"fix",6165,6180,,-2186.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-942,"fix",6180,6195,,-2194.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-943,"fix",6195,6210,,-2202.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-944,"fix",6210,6225,,-2210.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-945,"fix",6225,6240,,-2218.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-946,"fix",6240,6255,,-2226.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-947,"fix",6255,6270,,-2234.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-948,"fix",6270,6285,,-2242.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-949,"fix",6285,6300,,-2250.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-950,"fix",6300,6315,,-2258.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-951,"fix",6315,6330,,-2266.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-952,"fix",6330,6345,,-2274.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-953,"fix",6345,6360,,-2282.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-954,"fix",6360,6375,,-2291.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-955,"fix",6375,6390,,-2299.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-956,"fix",6390,6405,,-2307.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-957,"fix",6405,6420,,-2315.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-958,"fix",6420,6435,,-2323.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-959,"fix",6435,6450,,-2331.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-960,"fix",6450,6465,,-2339.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-961,"fix",6465,6480,,-2347.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-962,"fix",6480,6495,,-2355.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-963,"fix",6495,6510,,-2363.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-964,"fix",6510,6525,,-2371.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-965,"fix",6525,6540,,-2379.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-966,"fix",6540,6555,,-2387.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-967,"fix",6555,6570,,-2395.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-968,"fix",6570,6585,,-2403.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-969,"fix",6585,6600,,-2411.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-970,"fix",6600,6615,,-2419.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-971,"fix",6615,6630,,-2427.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-972,"fix",6630,6645,,-2435.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-973,"fix",6645,6660,,-2443.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-974,"fix",6660,6675,,-2451.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-975,"fix",6675,6690,,-2459.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-976,"fix",6690,6705,,-2467.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-977,"fix",6705,6720,,-2475.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-978,"fix",6720,6735,,-2483.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-979,"fix",6735,6750,,-2491.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-980,"fix",6750,6765,,-2499.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-981,"fix",6765,6780,,-2507.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-982,"fix",6780,6795,,-2515.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-983,"fix",6795,6810,,-2523.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-984,"fix",6810,6825,,-2531.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-985,"fix",6825,6840,,-2539.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-986,"fix",6840,6855,,-2547.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-987,"fix",6855,6870,,-2555.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-988,"fix",6870,6885,,-2563.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-989,"fix",6885,6900,,-2571.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-990,"fix",6900,6915,,-2579.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-991,"fix",6915,6930,,-2587.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-992,"fix",6930,6945,,-2595.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-993,"fix",6945,6960,,-2603.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-994,"fix",6960,6975,,-2612.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-995,"fix",6975,6990,,-2620.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-996,"fix",6990,7005,,-2628.05,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-997,"fix",7005,7020,,-2636.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-998,"fix",7020,7035,,-2644.10,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-999,"fix",7035,7050,,-2652.12,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1000,"fix",7050,7065,,-2660.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1001,"fix",7065,7080,,-2668.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1002,"fix",7080,7095,,-2676.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1003,"fix",7095,7110,,-2684.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1004,"fix",7110,7125,,-2692.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1005,"fix",7125,7140,,-2700.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1006,"fix",7140,7155,,-2708.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1007,"fix",7155,7170,,-2716.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1008,"fix",7170,7185,,-2724.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1009,"fix",7185,7200,,-2732.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1010,"fix",7200,7215,,-2740.40,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1011,"fix",7215,7230,,-2748.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1012,"fix",7230,7245,,-2756.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1013,"fix",7245,7260,,-2764.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1014,"fix",7260,7275,,-2772.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1015,"fix",7275,7290,,-2780.52,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1016,"fix",7290,7305,,-2788.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1017,"fix",7305,7320,,-2796.57,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1018,"fix",7320,7335,,-2804.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1019,"fix",7335,7350,,-2812.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1020,"fix",7350,7365,,-2820.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1021,"fix",7365,7380,,-2828.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1022,"fix",7380,7395,,-2836.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1023,"fix",7395,7410,,-2844.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1024,"fix",7410,7425,,-2852.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1025,"fix",7425,7440,,-2860.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1026,"fix",7440,7455,,-2868.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1027,"fix",7455,7470,,-2876.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1028,"fix",7470,7485,,-2884.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1029,"fix",7485,7500,,-2892.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-1030,"fix",7500,2147483647,,-2900.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
-,,,,,,,,,,,,,,
-1201,"fix",0,15,,-0,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1202,"fix",15,30,,-2.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1203,"fix",30,45,,-5.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1204,"fix",45,60,,-8.42,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1205,"fix",60,75,,-11.23,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1206,"fix",75,90,,-14.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1207,"fix",90,105,,-16.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1208,"fix",105,120,,-19.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1209,"fix",120,135,,-22.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1210,"fix",135,150,,-25.27,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1211,"fix",150,165,,-28.08,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1212,"fix",165,180,,-30.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1213,"fix",180,195,,-33.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1214,"fix",195,210,,-36.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1215,"fix",210,225,,-39.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1216,"fix",225,240,,-42.13,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1217,"fix",240,255,,-44.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1218,"fix",255,270,,-47.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1219,"fix",270,285,,-50.55,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1220,"fix",285,300,,-53.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1221,"fix",300,315,,-56.17,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1222,"fix",315,330,,-58.98,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1223,"fix",330,345,,-61.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1224,"fix",345,360,,-64.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1225,"fix",360,375,,-67.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1226,"fix",375,390,,-70.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1227,"fix",390,405,,-73.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1228,"fix",405,420,,-75.83,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1229,"fix",420,435,,-78.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1230,"fix",435,450,,-81.45,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1231,"fix",450,465,,-84.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1232,"fix",465,480,,-87.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1233,"fix",480,495,,-89.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1234,"fix",495,510,,-92.68,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1235,"fix",510,525,,-95.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1236,"fix",525,540,,-98.30,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1237,"fix",540,555,,-101.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1238,"fix",555,570,,-103.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1239,"fix",570,585,,-106.73,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1240,"fix",585,600,,-109.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1241,"fix",600,615,,-112.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1242,"fix",615,630,,-115.15,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1243,"fix",630,645,,-117.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1244,"fix",645,660,,-120.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1245,"fix",660,675,,-123.58,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1246,"fix",675,690,,-126.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1247,"fix",690,705,,-129.20,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1248,"fix",705,720,,-132.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1249,"fix",720,735,,-134.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1250,"fix",735,750,,-138.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1251,"fix",750,765,,-142.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1252,"fix",765,780,,-145.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1253,"fix",780,795,,-149.18,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1254,"fix",795,810,,-152.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1255,"fix",810,825,,-156.33,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1256,"fix",825,840,,-159.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1257,"fix",840,855,,-163.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1258,"fix",855,870,,-167.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1259,"fix",870,885,,-170.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1260,"fix",885,900,,-174.18,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1261,"fix",900,915,,-177.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1262,"fix",915,930,,-181.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1263,"fix",930,945,,-184.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1264,"fix",945,960,,-188.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1265,"fix",960,975,,-192.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1266,"fix",975,990,,-195.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1267,"fix",990,1005,,-199.18,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1268,"fix",1005,1020,,-202.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1269,"fix",1020,1035,,-206.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1270,"fix",1035,1050,,-209.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1271,"fix",1050,1065,,-213.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1272,"fix",1065,1080,,-217.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1273,"fix",1080,1095,,-220.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1274,"fix",1095,1110,,-224.18,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1275,"fix",1110,1125,,-227.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1276,"fix",1125,1140,,-231.32,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1277,"fix",1140,1155,,-234.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1278,"fix",1155,1170,,-238.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1279,"fix",1170,1185,,-242.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1280,"fix",1185,1200,,-245.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1281,"fix",1200,1215,,-249.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1282,"fix",1215,1230,,-253.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1283,"fix",1230,1245,,-258.23,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1284,"fix",1245,1260,,-262.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1285,"fix",1260,1275,,-266.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1286,"fix",1275,1290,,-271.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1287,"fix",1290,1305,,-275.37,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1288,"fix",1305,1320,,-281.08,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1289,"fix",1320,1335,,-286.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1290,"fix",1335,1350,,-292.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1291,"fix",1350,1365,,-298.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1292,"fix",1365,1380,,-303.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1293,"fix",1380,1395,,-309.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1294,"fix",1395,1410,,-315.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1295,"fix",1410,1425,,-321.08,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1296,"fix",1425,1440,,-326.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1297,"fix",1440,1455,,-332.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1298,"fix",1455,1470,,-338.22,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1299,"fix",1470,1485,,-343.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1300,"fix",1485,1500,,-349.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1301,"fix",1500,1515,,-355.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1302,"fix",1515,1530,,-361.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1303,"fix",1530,1545,,-366.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1304,"fix",1545,1560,,-372.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1305,"fix",1560,1575,,-378.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1306,"fix",1575,1590,,-383.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1307,"fix",1590,1605,,-389.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1308,"fix",1605,1620,,-395.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1309,"fix",1620,1635,,-401.07,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1310,"fix",1635,1650,,-406.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1311,"fix",1650,1665,,-412.50,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1312,"fix",1665,1680,,-418.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1313,"fix",1680,1695,,-423.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1314,"fix",1695,1710,,-429.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1315,"fix",1710,1725,,-435.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1316,"fix",1725,1740,,-442.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1317,"fix",1740,1755,,-448.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1318,"fix",1755,1770,,-454.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1319,"fix",1770,1785,,-460.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1320,"fix",1785,1800,,-466.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1321,"fix",1800,1815,,-473.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1322,"fix",1815,1830,,-480.60,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1323,"fix",1830,1845,,-487.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1324,"fix",1845,1860,,-494.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1325,"fix",1860,1875,,-501.62,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1326,"fix",1875,1890,,-508.63,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1327,"fix",1890,1905,,-515.63,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1328,"fix",1905,1920,,-522.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1329,"fix",1920,1935,,-529.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1330,"fix",1935,1950,,-536.65,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1331,"fix",1950,1965,,-543.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1332,"fix",1965,1980,,-550.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1333,"fix",1980,1995,,-557.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1334,"fix",1995,2010,,-564.67,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1335,"fix",2010,2025,,-571.68,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1336,"fix",2025,2040,,-578.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1337,"fix",2040,2055,,-585.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1338,"fix",2055,2070,,-592.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1339,"fix",2070,2085,,-599.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1340,"fix",2085,2100,,-606.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1341,"fix",2100,2115,,-613.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1342,"fix",2115,2130,,-620.72,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1343,"fix",2130,2145,,-627.73,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1344,"fix",2145,2160,,-634.73,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1345,"fix",2160,2175,,-641.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1346,"fix",2175,2190,,-648.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1347,"fix",2190,2205,,-655.75,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1348,"fix",2205,2220,,-662.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1349,"fix",2220,2235,,-669.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1350,"fix",2235,2250,,-676.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1351,"fix",2250,2265,,-683.77,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1352,"fix",2265,2280,,-690.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1353,"fix",2280,2295,,-697.78,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1354,"fix",2295,2310,,-704.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1355,"fix",2310,2325,,-711.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1356,"fix",2325,2340,,-718.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1357,"fix",2340,2355,,-725.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1358,"fix",2355,2370,,-732.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1359,"fix",2370,2385,,-739.82,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1360,"fix",2385,2400,,-746.83,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1361,"fix",2400,2415,,-753.83,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1362,"fix",2415,2430,,-760.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1363,"fix",2430,2445,,-767.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1364,"fix",2445,2460,,-774.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1365,"fix",2460,2475,,-781.85,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1366,"fix",2475,2490,,-788.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1367,"fix",2490,2505,,-795.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1368,"fix",2505,2520,,-802.87,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1369,"fix",2520,2535,,-809.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1370,"fix",2535,2550,,-816.88,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1371,"fix",2550,2565,,-823.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1372,"fix",2565,2580,,-830.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1373,"fix",2580,2595,,-837.90,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1374,"fix",2595,2610,,-844.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1375,"fix",2610,2625,,-851.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1376,"fix",2625,2640,,-858.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1377,"fix",2640,2655,,-865.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1378,"fix",2655,2670,,-872.93,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1379,"fix",2670,2685,,-879.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1380,"fix",2685,2700,,-886.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1381,"fix",2700,2715,,-893.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1382,"fix",2715,2730,,-900.95,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1383,"fix",2730,2745,,-907.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1384,"fix",2745,2760,,-914.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1385,"fix",2760,2775,,-921.97,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1386,"fix",2775,2790,,-928.98,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1387,"fix",2790,2805,,-935.98,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1388,"fix",2805,2820,,-942.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1389,"fix",2820,2835,,-949.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1390,"fix",2835,2850,,-957.00,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1391,"fix",2850,2865,,-964.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1392,"fix",2865,2880,,-971.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1393,"fix",2880,2895,,-978.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1394,"fix",2895,2910,,-985.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1395,"fix",2910,2925,,-992.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1396,"fix",2925,2940,,-999.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1397,"fix",2940,2955,,-1006.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1398,"fix",2955,2970,,-1013.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1399,"fix",2970,2985,,-1020.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1400,"fix",2985,3000,,-1027.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1401,"fix",3000,3015,,-1035.13,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1402,"fix",3015,3030,,-1042.35,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1403,"fix",3030,3045,,-1049.58,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1404,"fix",3045,3060,,-1056.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1405,"fix",3060,3075,,-1064.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1406,"fix",3075,3090,,-1071.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1407,"fix",3090,3105,,-1078.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1408,"fix",3105,3120,,-1085.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1409,"fix",3120,3135,,-1092.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1410,"fix",3135,3150,,-1100.13,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1411,"fix",3150,3165,,-1107.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1412,"fix",3165,3180,,-1114.58,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1413,"fix",3180,3195,,-1121.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1414,"fix",3195,3210,,-1129.02,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1415,"fix",3210,3225,,-1136.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1416,"fix",3225,3240,,-1143.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1417,"fix",3240,3255,,-1150.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1418,"fix",3255,3270,,-1157.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1419,"fix",3270,3285,,-1165.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1420,"fix",3285,3300,,-1172.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1421,"fix",3300,3315,,-1179.58,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1422,"fix",3315,3330,,-1186.80,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1423,"fix",3330,3345,,-1194.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1424,"fix",3345,3360,,-1201.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1425,"fix",3360,3375,,-1208.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1426,"fix",3375,3390,,-1215.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1427,"fix",3390,3405,,-1222.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1428,"fix",3405,3420,,-1230.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1429,"fix",3420,3435,,-1237.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1430,"fix",3435,3450,,-1244.58,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1431,"fix",3450,3465,,-1251.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1432,"fix",3465,3480,,-1259.03,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1433,"fix",3480,3495,,-1266.25,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1434,"fix",3495,3510,,-1273.47,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1435,"fix",3510,3525,,-1280.70,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1436,"fix",3525,3540,,-1287.92,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1437,"fix",3540,3555,,-1295.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1438,"fix",3555,3570,,-1302.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1439,"fix",3570,3585,,-1309.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1440,"fix",3585,3600,,-1316.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1441,"fix",3600,3615,,-1324.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1442,"fix",3615,3630,,-1332.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1443,"fix",3630,3645,,-1340.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1444,"fix",3645,3660,,-1348.29,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1445,"fix",3660,3675,,-1356.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1446,"fix",3675,3690,,-1364.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1447,"fix",3690,3705,,-1372.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1448,"fix",3705,3720,,-1380.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1449,"fix",3720,3735,,-1388.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1450,"fix",3735,3750,,-1396.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1451,"fix",3750,3765,,-1404.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1452,"fix",3765,3780,,-1412.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1453,"fix",3780,3795,,-1420.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1454,"fix",3795,3810,,-1428.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1455,"fix",3810,3825,,-1436.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1456,"fix",3825,3840,,-1444.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1457,"fix",3840,3855,,-1452.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1458,"fix",3855,3870,,-1460.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1459,"fix",3870,3885,,-1468.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1460,"fix",3885,3900,,-1476.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1461,"fix",3900,3915,,-1484.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1462,"fix",3915,3930,,-1492.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1463,"fix",3930,3945,,-1500.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1464,"fix",3945,3960,,-1508.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1465,"fix",3960,3975,,-1516.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1466,"fix",3975,3990,,-1524.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1467,"fix",3990,4005,,-1532.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1468,"fix",4005,4020,,-1540.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1469,"fix",4020,4035,,-1548.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1470,"fix",4035,4050,,-1556.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1471,"fix",4050,4065,,-1564.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1472,"fix",4065,4080,,-1572.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1473,"fix",4080,4095,,-1581.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1474,"fix",4095,4110,,-1589.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1475,"fix",4110,4125,,-1597.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1476,"fix",4125,4140,,-1605.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1477,"fix",4140,4155,,-1613.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1478,"fix",4155,4170,,-1621.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1479,"fix",4170,4185,,-1629.16,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1480,"fix",4185,4200,,-1637.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1481,"fix",4200,4215,,-1645.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1482,"fix",4215,4230,,-1653.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1483,"fix",4230,4245,,-1661.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1484,"fix",4245,4260,,-1669.29,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1485,"fix",4260,4275,,-1677.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1486,"fix",4275,4290,,-1685.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1487,"fix",4290,4305,,-1693.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1488,"fix",4305,4320,,-1701.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1489,"fix",4320,4335,,-1709.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1490,"fix",4335,4350,,-1717.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1491,"fix",4350,4365,,-1725.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1492,"fix",4365,4380,,-1733.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1493,"fix",4380,4395,,-1741.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1494,"fix",4395,4410,,-1749.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1495,"fix",4410,4425,,-1757.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1496,"fix",4425,4440,,-1765.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1497,"fix",4440,4455,,-1773.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1498,"fix",4455,4470,,-1781.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1499,"fix",4470,4485,,-1789.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1500,"fix",4485,4500,,-1797.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1501,"fix",4500,4515,,-1805.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1502,"fix",4515,4530,,-1813.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1503,"fix",4530,4545,,-1821.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1504,"fix",4545,4560,,-1829.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1505,"fix",4560,4575,,-1837.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1506,"fix",4575,4590,,-1845.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1507,"fix",4590,4605,,-1853.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1508,"fix",4605,4620,,-1861.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1509,"fix",4620,4635,,-1869.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1510,"fix",4635,4650,,-1877.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1511,"fix",4650,4665,,-1885.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1512,"fix",4665,4680,,-1893.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1513,"fix",4680,4695,,-1902.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1514,"fix",4695,4710,,-1910.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1515,"fix",4710,4725,,-1918.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1516,"fix",4725,4740,,-1926.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1517,"fix",4740,4755,,-1934.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1518,"fix",4755,4770,,-1942.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1519,"fix",4770,4785,,-1950.16,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1520,"fix",4785,4800,,-1958.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1521,"fix",4800,4815,,-1966.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1522,"fix",4815,4830,,-1974.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1523,"fix",4830,4845,,-1982.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1524,"fix",4845,4860,,-1990.29,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1525,"fix",4860,4875,,-1998.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1526,"fix",4875,4890,,-2006.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1527,"fix",4890,4905,,-2014.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1528,"fix",4905,4920,,-2022.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1529,"fix",4920,4935,,-2030.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1530,"fix",4935,4950,,-2038.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1531,"fix",4950,4965,,-2046.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1532,"fix",4965,4980,,-2054.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1533,"fix",4980,4995,,-2062.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1534,"fix",4995,5010,,-2070.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1535,"fix",5010,5025,,-2078.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1536,"fix",5025,5040,,-2086.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1537,"fix",5040,5055,,-2094.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1538,"fix",5055,5070,,-2102.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1539,"fix",5070,5085,,-2110.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1540,"fix",5085,5100,,-2118.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1541,"fix",5100,5115,,-2126.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1542,"fix",5115,5130,,-2134.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1543,"fix",5130,5145,,-2142.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1544,"fix",5145,5160,,-2150.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1545,"fix",5160,5175,,-2158.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1546,"fix",5175,5190,,-2166.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1547,"fix",5190,5205,,-2174.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1548,"fix",5205,5220,,-2182.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1549,"fix",5220,5235,,-2190.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1550,"fix",5235,5250,,-2198.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1551,"fix",5250,5265,,-2206.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1552,"fix",5265,5280,,-2214.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1553,"fix",5280,5295,,-2223.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1554,"fix",5295,5310,,-2231.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1555,"fix",5310,5325,,-2239.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1556,"fix",5325,5340,,-2247.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1557,"fix",5340,5355,,-2255.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1558,"fix",5355,5370,,-2263.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1559,"fix",5370,5385,,-2271.16,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1560,"fix",5385,5400,,-2279.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1561,"fix",5400,5415,,-2287.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1562,"fix",5415,5430,,-2295.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1563,"fix",5430,5445,,-2303.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1564,"fix",5445,5460,,-2311.29,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1565,"fix",5460,5475,,-2319.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1566,"fix",5475,5490,,-2327.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1567,"fix",5490,5505,,-2335.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1568,"fix",5505,5520,,-2343.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1569,"fix",5520,5535,,-2351.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1570,"fix",5535,5550,,-2359.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1571,"fix",5550,5565,,-2367.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1572,"fix",5565,5580,,-2375.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1573,"fix",5580,5595,,-2383.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1574,"fix",5595,5610,,-2391.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1575,"fix",5610,5625,,-2399.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1576,"fix",5625,5640,,-2407.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1577,"fix",5640,5655,,-2415.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1578,"fix",5655,5670,,-2423.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1579,"fix",5670,5685,,-2431.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1580,"fix",5685,5700,,-2439.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1581,"fix",5700,5715,,-2447.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1582,"fix",5715,5730,,-2455.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1583,"fix",5730,5745,,-2463.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1584,"fix",5745,5760,,-2471.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1585,"fix",5760,5775,,-2479.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1586,"fix",5775,5790,,-2487.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1587,"fix",5790,5805,,-2495.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1588,"fix",5805,5820,,-2503.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1589,"fix",5820,5835,,-2511.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1590,"fix",5835,5850,,-2519.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1591,"fix",5850,5865,,-2527.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1592,"fix",5865,5880,,-2535.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1593,"fix",5880,5895,,-2544.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1594,"fix",5895,5910,,-2552.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1595,"fix",5910,5925,,-2560.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1596,"fix",5925,5940,,-2568.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1597,"fix",5940,5955,,-2576.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1598,"fix",5955,5970,,-2584.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1599,"fix",5970,5985,,-2592.16,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1600,"fix",5985,6000,,-2600.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1601,"fix",6000,6015,,-2608.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1602,"fix",6015,6030,,-2616.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1603,"fix",6030,6045,,-2624.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1604,"fix",6045,6060,,-2632.29,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1605,"fix",6060,6075,,-2640.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1606,"fix",6075,6090,,-2648.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1607,"fix",6090,6105,,-2656.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1608,"fix",6105,6120,,-2664.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1609,"fix",6120,6135,,-2672.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1610,"fix",6135,6150,,-2680.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1611,"fix",6150,6165,,-2688.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1612,"fix",6165,6180,,-2696.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1613,"fix",6180,6195,,-2704.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1614,"fix",6195,6210,,-2712.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1615,"fix",6210,6225,,-2720.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1616,"fix",6225,6240,,-2728.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1617,"fix",6240,6255,,-2736.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1618,"fix",6255,6270,,-2744.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1619,"fix",6270,6285,,-2752.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1620,"fix",6285,6300,,-2760.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1621,"fix",6300,6315,,-2768.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1622,"fix",6315,6330,,-2776.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1623,"fix",6330,6345,,-2784.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1624,"fix",6345,6360,,-2792.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1625,"fix",6360,6375,,-2800.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1626,"fix",6375,6390,,-2808.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1627,"fix",6390,6405,,-2816.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1628,"fix",6405,6420,,-2824.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1629,"fix",6420,6435,,-2832.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1630,"fix",6435,6450,,-2840.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1631,"fix",6450,6465,,-2848.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1632,"fix",6465,6480,,-2856.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1633,"fix",6480,6495,,-2865.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1634,"fix",6495,6510,,-2873.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1635,"fix",6510,6525,,-2881.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1636,"fix",6525,6540,,-2889.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1637,"fix",6540,6555,,-2897.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1638,"fix",6555,6570,,-2905.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1639,"fix",6570,6585,,-2913.16,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1640,"fix",6585,6600,,-2921.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1641,"fix",6600,6615,,-2929.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1642,"fix",6615,6630,,-2937.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1643,"fix",6630,6645,,-2945.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1644,"fix",6645,6660,,-2953.29,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1645,"fix",6660,6675,,-2961.31,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1646,"fix",6675,6690,,-2969.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1647,"fix",6690,6705,,-2977.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1648,"fix",6705,6720,,-2985.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1649,"fix",6720,6735,,-2993.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1650,"fix",6735,6750,,-3001.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1651,"fix",6750,6765,,-3009.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1652,"fix",6765,6780,,-3017.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1653,"fix",6780,6795,,-3025.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1654,"fix",6795,6810,,-3033.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1655,"fix",6810,6825,,-3041.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1656,"fix",6825,6840,,-3049.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1657,"fix",6840,6855,,-3057.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1658,"fix",6855,6870,,-3065.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1659,"fix",6870,6885,,-3073.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1660,"fix",6885,6900,,-3081.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1661,"fix",6900,6915,,-3089.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1662,"fix",6915,6930,,-3097.74,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1663,"fix",6930,6945,,-3105.76,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1664,"fix",6945,6960,,-3113.79,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1665,"fix",6960,6975,,-3121.81,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1666,"fix",6975,6990,,-3129.84,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1667,"fix",6990,7005,,-3137.86,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1668,"fix",7005,7020,,-3145.89,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1669,"fix",7020,7035,,-3153.91,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1670,"fix",7035,7050,,-3161.94,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1671,"fix",7050,7065,,-3169.96,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1672,"fix",7065,7080,,-3177.99,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1673,"fix",7080,7095,,-3186.01,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1674,"fix",7095,7110,,-3194.04,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1675,"fix",7110,7125,,-3202.06,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1676,"fix",7125,7140,,-3210.09,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1677,"fix",7140,7155,,-3218.11,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1678,"fix",7155,7170,,-3226.14,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1679,"fix",7170,7185,,-3234.16,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1680,"fix",7185,7200,,-3242.19,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1681,"fix",7200,7215,,-3250.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1682,"fix",7215,7230,,-3258.24,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1683,"fix",7230,7245,,-3266.26,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1684,"fix",7245,7260,,-3274.29,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1685,"fix",7260,7275,,-3282.21,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1686,"fix",7275,7290,,-3290.34,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1687,"fix",7290,7305,,-3298.36,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1688,"fix",7305,7320,,-3306.39,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1689,"fix",7320,7335,,-3314.41,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1690,"fix",7335,7350,,-3322.44,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1691,"fix",7350,7365,,-3330.46,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1692,"fix",7365,7380,,-3338.49,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1693,"fix",7380,7395,,-3346.51,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1694,"fix",7395,7410,,-3354.54,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1695,"fix",7410,7425,,-3362.56,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1696,"fix",7425,7440,,-3370.59,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1697,"fix",7440,7455,,-3378.61,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1698,"fix",7455,7470,,-3386.64,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1699,"fix",7470,7485,,-3394.66,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1700,"fix",7485,7500,,-3402.69,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-1701,"fix",7500,2147483647,,-3410.71,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
-,,,,,,,,,,,,,,
-1410,"fix",1,1,,35,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1411,"fix",2,2,,95,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1412,"fix",3,3,,248,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1413,"fix",4,4,,454,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1414,"fix",5,5,,671,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1415,"fix",6,6,,887,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1416,"fix",7,7,,1105,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1417,"fix",8,8,,1344,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1418,"fix",9,9,,1590,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1419,"fix",10,10,,1836,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1420,"fix",11,11,,2082,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1421,"fix",12,12,,2328,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1422,"fix",13,13,,2574,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1423,"fix",14,14,,2820,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1424,"fix",15,15,,3066,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1425,"fix",16,16,,3312,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1426,"fix",17,17,,3558,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1427,"fix",18,18,,3804,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1428,"fix",19,19,,4050,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
-1429,"fix",20,20,,4296,"Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+,,,,,,,,,,,,,,,
+600,"fix",0,1065,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+601,"fix",1065,1080,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+602,"fix",1080,1095,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+603,"fix",1095,1110,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+604,"fix",1110,1125,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+605,"fix",1125,1140,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+606,"fix",1140,1155,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+607,"fix",1155,1170,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+608,"fix",1170,1185,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+609,"fix",1185,1200,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+610,"fix",1200,1215,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+611,"fix",1215,1230,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+612,"fix",1230,1245,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+613,"fix",1245,1260,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+614,"fix",1260,1275,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+615,"fix",1275,1290,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+616,"fix",1290,1305,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+617,"fix",1305,1320,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+618,"fix",1320,1335,,-1.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+619,"fix",1335,1350,,-5.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+620,"fix",1350,1365,,-8.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+621,"fix",1365,1380,,-12.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+622,"fix",1380,1395,,-16.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+623,"fix",1395,1410,,-19.63,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+624,"fix",1410,1425,,-23.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+625,"fix",1425,1440,,-26.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+626,"fix",1440,1455,,-30.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+627,"fix",1455,1470,,-33.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+628,"fix",1470,1485,,-37.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+629,"fix",1485,1500,,-41.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+630,"fix",1500,1515,,-44.63,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+631,"fix",1515,1530,,-48.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+632,"fix",1530,1545,,-51.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+633,"fix",1545,1560,,-55.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+634,"fix",1560,1575,,-58.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+635,"fix",1575,1590,,-62.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+636,"fix",1590,1605,,-66.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+637,"fix",1605,1620,,-69.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+638,"fix",1620,1635,,-73.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+639,"fix",1635,1650,,-76.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+640,"fix",1650,1665,,-80.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+641,"fix",1665,1680,,-84.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+642,"fix",1680,1695,,-89.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+643,"fix",1695,1710,,-93.08,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+644,"fix",1710,1725,,-97.48,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+645,"fix",1725,1740,,-101.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+646,"fix",1740,1755,,-106.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+647,"fix",1755,1770,,-110.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+648,"fix",1770,1785,,-115.23,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+649,"fix",1785,1800,,-120.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+650,"fix",1800,1815,,-126.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+651,"fix",1815,1830,,-131.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+652,"fix",1830,1845,,-137.29,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+653,"fix",1845,1860,,-142.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+654,"fix",1860,1875,,-148.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+655,"fix",1875,1890,,-153.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+656,"fix",1890,1905,,-159.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+657,"fix",1905,1920,,-164.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+658,"fix",1920,1935,,-170.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+659,"fix",1935,1950,,-175.98,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+660,"fix",1950,1965,,-181.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+661,"fix",1965,1980,,-187.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+662,"fix",1980,1995,,-192.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+663,"fix",1995,2010,,-198.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+664,"fix",2010,2025,,-203.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+665,"fix",2025,2040,,-209.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+666,"fix",2040,2055,,-214.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+667,"fix",2055,2070,,-220.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+668,"fix",2070,2085,,-225.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+669,"fix",2085,2100,,-231.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+670,"fix",2100,2115,,-236.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+671,"fix",2115,2130,,-242.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+672,"fix",2130,2145,,-247.83,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+673,"fix",2145,2160,,-253.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+674,"fix",2160,2175,,-258.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+675,"fix",2175,2190,,-264.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+676,"fix",2190,2205,,-269.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+677,"fix",2205,2220,,-275.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+678,"fix",2220,2235,,-280.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+679,"fix",2235,2250,,-286.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+680,"fix",2250,2265,,-292.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+681,"fix",2265,2280,,-297.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+682,"fix",2280,2295,,-303.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+683,"fix",2295,2310,,-308.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+684,"fix",2310,2325,,-314.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+685,"fix",2325,2340,,-319.68,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+686,"fix",2340,2355,,-325.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+687,"fix",2355,2370,,-330.73,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+688,"fix",2370,2385,,-336.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+689,"fix",2385,2400,,-341.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+690,"fix",2400,2415,,-347.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+691,"fix",2415,2430,,-352.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+692,"fix",2430,2445,,-358.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+693,"fix",2445,2460,,-364.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+694,"fix",2460,2475,,-370.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+695,"fix",2475,2490,,-376.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+696,"fix",2490,2505,,-382.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+697,"fix",2505,2520,,-388.38,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+698,"fix",2520,2535,,-394.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+699,"fix",2535,2550,,-400.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+700,"fix",2550,2565,,-406.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+701,"fix",2565,2580,,-412.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+702,"fix",2580,2595,,-418.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+703,"fix",2595,2610,,-424.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+704,"fix",2610,2625,,-430.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+705,"fix",2625,2640,,-436.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+706,"fix",2640,2655,,-443.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+707,"fix",2655,2670,,-449.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+708,"fix",2670,2685,,-455.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+709,"fix",2685,2700,,-461.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+710,"fix",2700,2715,,-467.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+711,"fix",2715,2730,,-473.38,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+712,"fix",2730,2745,,-479.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+713,"fix",2745,2760,,-485.53,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+714,"fix",2760,2775,,-491.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+715,"fix",2775,2790,,-497.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+716,"fix",2790,2805,,-503.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+717,"fix",2805,2820,,-509.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+718,"fix",2820,2835,,-515.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+719,"fix",2835,2850,,-521.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+720,"fix",2850,2865,,-528.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+721,"fix",2865,2880,,-534.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+722,"fix",2880,2895,,-540.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+723,"fix",2895,2910,,-546.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+724,"fix",2910,2925,,-552.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+725,"fix",2925,2940,,-558.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+726,"fix",2940,2955,,-564.63,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+727,"fix",2955,2970,,-570.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+728,"fix",2970,2985,,-577.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+729,"fix",2985,3000,,-583.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+730,"fix",3000,3015,,-589.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+731,"fix",3015,3030,,-595.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+732,"fix",3030,3045,,-602.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+733,"fix",3045,3060,,-608.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+734,"fix",3060,3075,,-614.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+735,"fix",3075,3090,,-620.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+736,"fix",3090,3105,,-627.23,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+737,"fix",3105,3120,,-633.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+738,"fix",3120,3135,,-639.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+739,"fix",3135,3150,,-646.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+740,"fix",3150,3165,,-652.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+741,"fix",3165,3180,,-658.53,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+742,"fix",3180,3195,,-664.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+743,"fix",3195,3210,,-671.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+744,"fix",3210,3225,,-677.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+745,"fix",3225,3240,,-683.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+746,"fix",3240,3255,,-689.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+747,"fix",3255,3270,,-696.08,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+748,"fix",3270,3285,,-702.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+749,"fix",3285,3300,,-709.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+750,"fix",3300,3315,,-716.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+751,"fix",3315,3330,,-723.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+752,"fix",3330,3345,,-730.98,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+753,"fix",3345,3360,,-738.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+754,"fix",3360,3375,,-745.43,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+755,"fix",3375,3390,,-752.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+756,"fix",3390,3405,,-759.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+757,"fix",3405,3420,,-767.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+758,"fix",3420,3435,,-774.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+759,"fix",3435,3450,,-781.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+760,"fix",3450,3465,,-788.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+761,"fix",3465,3480,,-795.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+762,"fix",3480,3495,,-803.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+763,"fix",3495,3510,,-810.43,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+764,"fix",3510,3525,,-817.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+765,"fix",3525,3540,,-824.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+766,"fix",3540,3555,,-832.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+767,"fix",3555,3570,,-839.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+768,"fix",3570,3585,,-846.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+769,"fix",3585,3600,,-853.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+770,"fix",3600,3615,,-860.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+771,"fix",3615,3630,,-868.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+772,"fix",3630,3645,,-875.43,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+773,"fix",3645,3660,,-882.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+774,"fix",3660,3675,,-889.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+775,"fix",3675,3690,,-897.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+776,"fix",3690,3705,,-904.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+777,"fix",3705,3720,,-911.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+778,"fix",3720,3735,,-918.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+779,"fix",3735,3750,,-925.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+780,"fix",3750,3765,,-933.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+781,"fix",3765,3780,,-940.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+782,"fix",3780,3795,,-947.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+783,"fix",3795,3810,,-954.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+784,"fix",3810,3825,,-962.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+785,"fix",3825,3840,,-969.33,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+786,"fix",3840,3855,,-976.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+787,"fix",3855,3870,,-983.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+788,"fix",3870,3885,,-990.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+789,"fix",3885,3900,,-998.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+790,"fix",3900,3915,,-1005.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+791,"fix",3915,3930,,-1012.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+792,"fix",3930,3945,,-1019.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+793,"fix",3945,3960,,-1027.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+794,"fix",3960,3975,,-1034.33,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+795,"fix",3975,3990,,-1041.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+796,"fix",3990,4005,,-1048.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+797,"fix",4005,4020,,-1056.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+798,"fix",4020,4035,,-1063.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+799,"fix",4035,4050,,-1070.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+800,"fix",4050,4065,,-1077.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+801,"fix",4065,4080,,-1084.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+802,"fix",4080,4095,,-1092.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+803,"fix",4095,4110,,-1099.33,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+804,"fix",4110,4125,,-1106.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+805,"fix",4125,4140,,-1113.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+806,"fix",4140,4155,,-1121.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+807,"fix",4155,4170,,-1128.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+808,"fix",4170,4185,,-1135.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+809,"fix",4185,4200,,-1142.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+810,"fix",4200,4215,,-1149.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+811,"fix",4215,4230,,-1157.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+812,"fix",4230,4245,,-1164.33,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+813,"fix",4245,4260,,-1171.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+814,"fix",4260,4275,,-1178.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+815,"fix",4275,4290,,-1186.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+816,"fix",4290,4305,,-1193.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+817,"fix",4305,4320,,-1200.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+818,"fix",4320,4335,,-1207.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+819,"fix",4335,4350,,-1214.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+820,"fix",4350,4365,,-1222.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+821,"fix",4365,4380,,-1229.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+822,"fix",4380,4395,,-1236.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+823,"fix",4395,4410,,-1243.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+824,"fix",4410,4425,,-1251.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+825,"fix",4425,4440,,-1258.23,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+826,"fix",4440,4455,,-1265.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+827,"fix",4455,4470,,-1272.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+828,"fix",4470,4485,,-1279.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+829,"fix",4485,4500,,-1287.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+830,"fix",4500,4515,,-1295.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+831,"fix",4515,4530,,-1303.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+832,"fix",4530,4545,,-1311.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+833,"fix",4545,4560,,-1319.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+834,"fix",4560,4575,,-1328.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+835,"fix",4575,4590,,-1336.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+836,"fix",4590,4605,,-1344.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+837,"fix",4605,4620,,-1352.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+838,"fix",4620,4635,,-1360.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+839,"fix",4635,4650,,-1368.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+840,"fix",4650,4665,,-1376.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+841,"fix",4665,4680,,-1384.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+842,"fix",4680,4695,,-1392.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+843,"fix",4695,4710,,-1400.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+844,"fix",4710,4725,,-1408.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+845,"fix",4725,4740,,-1416.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+846,"fix",4740,4755,,-1424.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+847,"fix",4755,4770,,-1432.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+848,"fix",4770,4785,,-1440.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+849,"fix",4785,4800,,-1448.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+850,"fix",4800,4815,,-1456.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+851,"fix",4815,4830,,-1464.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+852,"fix",4830,4845,,-1472.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+853,"fix",4845,4860,,-1480.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+854,"fix",4860,4875,,-1488.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+855,"fix",4875,4890,,-1496.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+856,"fix",4890,4905,,-1504.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+857,"fix",4905,4920,,-1512.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+858,"fix",4920,4935,,-1520.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+859,"fix",4935,4950,,-1528.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+860,"fix",4950,4965,,-1536.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+861,"fix",4965,4980,,-1544.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+862,"fix",4980,4995,,-1552.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+863,"fix",4995,5010,,-1560.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+864,"fix",5010,5025,,-1568.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+865,"fix",5025,5040,,-1576.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+866,"fix",5040,5055,,-1584.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+867,"fix",5055,5070,,-1592.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+868,"fix",5070,5085,,-1600.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+869,"fix",5085,5100,,-1608.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+870,"fix",5100,5115,,-1616.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+871,"fix",5115,5130,,-1624.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+872,"fix",5130,5145,,-1632.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+873,"fix",5145,5160,,-1640.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+874,"fix",5160,5175,,-1649.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+875,"fix",5175,5190,,-1657.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+876,"fix",5190,5205,,-1665.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+877,"fix",5205,5220,,-1673.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+878,"fix",5220,5235,,-1681.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+879,"fix",5235,5250,,-1689.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+880,"fix",5250,5265,,-1697.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+881,"fix",5265,5280,,-1705.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+882,"fix",5280,5295,,-1713.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+883,"fix",5295,5310,,-1721.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+884,"fix",5310,5325,,-1729.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+885,"fix",5325,5340,,-1737.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+886,"fix",5340,5355,,-1745.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+887,"fix",5355,5370,,-1753.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+888,"fix",5370,5385,,-1761.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+889,"fix",5385,5400,,-1769.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+890,"fix",5400,5415,,-1777.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+891,"fix",5415,5430,,-1785.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+892,"fix",5430,5445,,-1793.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+893,"fix",5445,5460,,-1801.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+894,"fix",5460,5475,,-1809.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+895,"fix",5475,5490,,-1817.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+896,"fix",5490,5505,,-1825.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+897,"fix",5505,5520,,-1833.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+898,"fix",5520,5535,,-1841.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+899,"fix",5535,5550,,-1849.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+900,"fix",5550,5565,,-1857.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+901,"fix",5565,5580,,-1865.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+902,"fix",5580,5595,,-1873.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+903,"fix",5595,5610,,-1881.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+904,"fix",5610,5625,,-1889.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+905,"fix",5625,5640,,-1897.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+906,"fix",5640,5655,,-1905.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+907,"fix",5655,5670,,-1913.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+908,"fix",5670,5685,,-1921.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+909,"fix",5685,5700,,-1929.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+910,"fix",5700,5715,,-1937.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+911,"fix",5715,5730,,-1945.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+912,"fix",5730,5745,,-1953.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+913,"fix",5745,5760,,-1961.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+914,"fix",5760,5775,,-1970.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+915,"fix",5775,5790,,-1978.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+916,"fix",5790,5805,,-1986.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+917,"fix",5805,5820,,-1994.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+918,"fix",5820,5835,,-2002.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+919,"fix",5835,5850,,-2010.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+920,"fix",5850,5865,,-2018.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+921,"fix",5865,5880,,-2026.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+922,"fix",5880,5895,,-2034.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+923,"fix",5895,5910,,-2042.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+924,"fix",5910,5925,,-2050.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+925,"fix",5925,5940,,-2058.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+926,"fix",5940,5955,,-2066.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+927,"fix",5955,5970,,-2074.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+928,"fix",5970,5985,,-2082.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+929,"fix",5985,6000,,-2090.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+930,"fix",6000,6015,,-2098.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+931,"fix",6015,6030,,-2106.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+932,"fix",6030,6045,,-2114.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+933,"fix",6045,6060,,-2122.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+934,"fix",6060,6075,,-2130.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+935,"fix",6075,6090,,-2138.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+936,"fix",6090,6105,,-2146.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+937,"fix",6105,6120,,-2154.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+938,"fix",6120,6135,,-2162.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+939,"fix",6135,6150,,-2170.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+940,"fix",6150,6165,,-2178.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+941,"fix",6165,6180,,-2186.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+942,"fix",6180,6195,,-2194.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+943,"fix",6195,6210,,-2202.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+944,"fix",6210,6225,,-2210.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+945,"fix",6225,6240,,-2218.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+946,"fix",6240,6255,,-2226.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+947,"fix",6255,6270,,-2234.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+948,"fix",6270,6285,,-2242.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+949,"fix",6285,6300,,-2250.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+950,"fix",6300,6315,,-2258.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+951,"fix",6315,6330,,-2266.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+952,"fix",6330,6345,,-2274.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+953,"fix",6345,6360,,-2282.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+954,"fix",6360,6375,,-2291.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+955,"fix",6375,6390,,-2299.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+956,"fix",6390,6405,,-2307.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+957,"fix",6405,6420,,-2315.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+958,"fix",6420,6435,,-2323.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+959,"fix",6435,6450,,-2331.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+960,"fix",6450,6465,,-2339.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+961,"fix",6465,6480,,-2347.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+962,"fix",6480,6495,,-2355.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+963,"fix",6495,6510,,-2363.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+964,"fix",6510,6525,,-2371.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+965,"fix",6525,6540,,-2379.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+966,"fix",6540,6555,,-2387.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+967,"fix",6555,6570,,-2395.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+968,"fix",6570,6585,,-2403.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+969,"fix",6585,6600,,-2411.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+970,"fix",6600,6615,,-2419.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+971,"fix",6615,6630,,-2427.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+972,"fix",6630,6645,,-2435.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+973,"fix",6645,6660,,-2443.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+974,"fix",6660,6675,,-2451.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+975,"fix",6675,6690,,-2459.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+976,"fix",6690,6705,,-2467.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+977,"fix",6705,6720,,-2475.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+978,"fix",6720,6735,,-2483.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+979,"fix",6735,6750,,-2491.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+980,"fix",6750,6765,,-2499.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+981,"fix",6765,6780,,-2507.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+982,"fix",6780,6795,,-2515.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+983,"fix",6795,6810,,-2523.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+984,"fix",6810,6825,,-2531.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+985,"fix",6825,6840,,-2539.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+986,"fix",6840,6855,,-2547.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+987,"fix",6855,6870,,-2555.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+988,"fix",6870,6885,,-2563.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+989,"fix",6885,6900,,-2571.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+990,"fix",6900,6915,,-2579.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+991,"fix",6915,6930,,-2587.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+992,"fix",6930,6945,,-2595.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+993,"fix",6945,6960,,-2603.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+994,"fix",6960,6975,,-2612.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+995,"fix",6975,6990,,-2620.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+996,"fix",6990,7005,,-2628.05,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+997,"fix",7005,7020,,-2636.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+998,"fix",7020,7035,,-2644.10,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+999,"fix",7035,7050,,-2652.12,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1000,"fix",7050,7065,,-2660.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1001,"fix",7065,7080,,-2668.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1002,"fix",7080,7095,,-2676.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1003,"fix",7095,7110,,-2684.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1004,"fix",7110,7125,,-2692.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1005,"fix",7125,7140,,-2700.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1006,"fix",7140,7155,,-2708.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1007,"fix",7155,7170,,-2716.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1008,"fix",7170,7185,,-2724.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1009,"fix",7185,7200,,-2732.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1010,"fix",7200,7215,,-2740.40,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1011,"fix",7215,7230,,-2748.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1012,"fix",7230,7245,,-2756.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1013,"fix",7245,7260,,-2764.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1014,"fix",7260,7275,,-2772.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1015,"fix",7275,7290,,-2780.52,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1016,"fix",7290,7305,,-2788.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1017,"fix",7305,7320,,-2796.57,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1018,"fix",7320,7335,,-2804.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1019,"fix",7335,7350,,-2812.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1020,"fix",7350,7365,,-2820.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1021,"fix",7365,7380,,-2828.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1022,"fix",7380,7395,,-2836.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1023,"fix",7395,7410,,-2844.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1024,"fix",7410,7425,,-2852.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1025,"fix",7425,7440,,-2860.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1026,"fix",7440,7455,,-2868.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1027,"fix",7455,7470,,-2876.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1028,"fix",7470,7485,,-2884.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1029,"fix",7485,7500,,-2892.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+1030,"fix",7500,2147483647,,-2900.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeII","range","GROSS",,"contrib_register_pp"
+,,,,,,,,,,,,,,,
+1201,"fix",0,15,,-0,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1202,"fix",15,30,,-2.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1203,"fix",30,45,,-5.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1204,"fix",45,60,,-8.42,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1205,"fix",60,75,,-11.23,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1206,"fix",75,90,,-14.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1207,"fix",90,105,,-16.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1208,"fix",105,120,,-19.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1209,"fix",120,135,,-22.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1210,"fix",135,150,,-25.27,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1211,"fix",150,165,,-28.08,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1212,"fix",165,180,,-30.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1213,"fix",180,195,,-33.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1214,"fix",195,210,,-36.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1215,"fix",210,225,,-39.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1216,"fix",225,240,,-42.13,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1217,"fix",240,255,,-44.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1218,"fix",255,270,,-47.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1219,"fix",270,285,,-50.55,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1220,"fix",285,300,,-53.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1221,"fix",300,315,,-56.17,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1222,"fix",315,330,,-58.98,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1223,"fix",330,345,,-61.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1224,"fix",345,360,,-64.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1225,"fix",360,375,,-67.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1226,"fix",375,390,,-70.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1227,"fix",390,405,,-73.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1228,"fix",405,420,,-75.83,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1229,"fix",420,435,,-78.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1230,"fix",435,450,,-81.45,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1231,"fix",450,465,,-84.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1232,"fix",465,480,,-87.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1233,"fix",480,495,,-89.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1234,"fix",495,510,,-92.68,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1235,"fix",510,525,,-95.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1236,"fix",525,540,,-98.30,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1237,"fix",540,555,,-101.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1238,"fix",555,570,,-103.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1239,"fix",570,585,,-106.73,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1240,"fix",585,600,,-109.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1241,"fix",600,615,,-112.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1242,"fix",615,630,,-115.15,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1243,"fix",630,645,,-117.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1244,"fix",645,660,,-120.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1245,"fix",660,675,,-123.58,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1246,"fix",675,690,,-126.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1247,"fix",690,705,,-129.20,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1248,"fix",705,720,,-132.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1249,"fix",720,735,,-134.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1250,"fix",735,750,,-138.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1251,"fix",750,765,,-142.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1252,"fix",765,780,,-145.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1253,"fix",780,795,,-149.18,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1254,"fix",795,810,,-152.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1255,"fix",810,825,,-156.33,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1256,"fix",825,840,,-159.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1257,"fix",840,855,,-163.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1258,"fix",855,870,,-167.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1259,"fix",870,885,,-170.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1260,"fix",885,900,,-174.18,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1261,"fix",900,915,,-177.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1262,"fix",915,930,,-181.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1263,"fix",930,945,,-184.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1264,"fix",945,960,,-188.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1265,"fix",960,975,,-192.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1266,"fix",975,990,,-195.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1267,"fix",990,1005,,-199.18,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1268,"fix",1005,1020,,-202.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1269,"fix",1020,1035,,-206.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1270,"fix",1035,1050,,-209.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1271,"fix",1050,1065,,-213.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1272,"fix",1065,1080,,-217.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1273,"fix",1080,1095,,-220.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1274,"fix",1095,1110,,-224.18,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1275,"fix",1110,1125,,-227.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1276,"fix",1125,1140,,-231.32,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1277,"fix",1140,1155,,-234.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1278,"fix",1155,1170,,-238.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1279,"fix",1170,1185,,-242.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1280,"fix",1185,1200,,-245.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1281,"fix",1200,1215,,-249.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1282,"fix",1215,1230,,-253.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1283,"fix",1230,1245,,-258.23,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1284,"fix",1245,1260,,-262.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1285,"fix",1260,1275,,-266.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1286,"fix",1275,1290,,-271.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1287,"fix",1290,1305,,-275.37,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1288,"fix",1305,1320,,-281.08,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1289,"fix",1320,1335,,-286.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1290,"fix",1335,1350,,-292.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1291,"fix",1350,1365,,-298.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1292,"fix",1365,1380,,-303.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1293,"fix",1380,1395,,-309.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1294,"fix",1395,1410,,-315.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1295,"fix",1410,1425,,-321.08,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1296,"fix",1425,1440,,-326.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1297,"fix",1440,1455,,-332.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1298,"fix",1455,1470,,-338.22,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1299,"fix",1470,1485,,-343.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1300,"fix",1485,1500,,-349.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1301,"fix",1500,1515,,-355.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1302,"fix",1515,1530,,-361.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1303,"fix",1530,1545,,-366.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1304,"fix",1545,1560,,-372.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1305,"fix",1560,1575,,-378.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1306,"fix",1575,1590,,-383.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1307,"fix",1590,1605,,-389.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1308,"fix",1605,1620,,-395.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1309,"fix",1620,1635,,-401.07,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1310,"fix",1635,1650,,-406.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1311,"fix",1650,1665,,-412.50,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1312,"fix",1665,1680,,-418.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1313,"fix",1680,1695,,-423.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1314,"fix",1695,1710,,-429.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1315,"fix",1710,1725,,-435.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1316,"fix",1725,1740,,-442.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1317,"fix",1740,1755,,-448.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1318,"fix",1755,1770,,-454.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1319,"fix",1770,1785,,-460.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1320,"fix",1785,1800,,-466.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1321,"fix",1800,1815,,-473.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1322,"fix",1815,1830,,-480.60,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1323,"fix",1830,1845,,-487.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1324,"fix",1845,1860,,-494.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1325,"fix",1860,1875,,-501.62,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1326,"fix",1875,1890,,-508.63,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1327,"fix",1890,1905,,-515.63,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1328,"fix",1905,1920,,-522.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1329,"fix",1920,1935,,-529.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1330,"fix",1935,1950,,-536.65,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1331,"fix",1950,1965,,-543.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1332,"fix",1965,1980,,-550.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1333,"fix",1980,1995,,-557.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1334,"fix",1995,2010,,-564.67,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1335,"fix",2010,2025,,-571.68,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1336,"fix",2025,2040,,-578.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1337,"fix",2040,2055,,-585.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1338,"fix",2055,2070,,-592.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1339,"fix",2070,2085,,-599.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1340,"fix",2085,2100,,-606.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1341,"fix",2100,2115,,-613.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1342,"fix",2115,2130,,-620.72,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1343,"fix",2130,2145,,-627.73,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1344,"fix",2145,2160,,-634.73,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1345,"fix",2160,2175,,-641.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1346,"fix",2175,2190,,-648.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1347,"fix",2190,2205,,-655.75,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1348,"fix",2205,2220,,-662.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1349,"fix",2220,2235,,-669.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1350,"fix",2235,2250,,-676.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1351,"fix",2250,2265,,-683.77,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1352,"fix",2265,2280,,-690.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1353,"fix",2280,2295,,-697.78,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1354,"fix",2295,2310,,-704.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1355,"fix",2310,2325,,-711.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1356,"fix",2325,2340,,-718.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1357,"fix",2340,2355,,-725.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1358,"fix",2355,2370,,-732.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1359,"fix",2370,2385,,-739.82,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1360,"fix",2385,2400,,-746.83,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1361,"fix",2400,2415,,-753.83,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1362,"fix",2415,2430,,-760.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1363,"fix",2430,2445,,-767.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1364,"fix",2445,2460,,-774.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1365,"fix",2460,2475,,-781.85,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1366,"fix",2475,2490,,-788.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1367,"fix",2490,2505,,-795.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1368,"fix",2505,2520,,-802.87,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1369,"fix",2520,2535,,-809.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1370,"fix",2535,2550,,-816.88,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1371,"fix",2550,2565,,-823.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1372,"fix",2565,2580,,-830.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1373,"fix",2580,2595,,-837.90,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1374,"fix",2595,2610,,-844.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1375,"fix",2610,2625,,-851.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1376,"fix",2625,2640,,-858.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1377,"fix",2640,2655,,-865.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1378,"fix",2655,2670,,-872.93,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1379,"fix",2670,2685,,-879.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1380,"fix",2685,2700,,-886.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1381,"fix",2700,2715,,-893.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1382,"fix",2715,2730,,-900.95,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1383,"fix",2730,2745,,-907.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1384,"fix",2745,2760,,-914.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1385,"fix",2760,2775,,-921.97,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1386,"fix",2775,2790,,-928.98,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1387,"fix",2790,2805,,-935.98,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1388,"fix",2805,2820,,-942.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1389,"fix",2820,2835,,-949.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1390,"fix",2835,2850,,-957.00,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1391,"fix",2850,2865,,-964.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1392,"fix",2865,2880,,-971.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1393,"fix",2880,2895,,-978.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1394,"fix",2895,2910,,-985.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1395,"fix",2910,2925,,-992.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1396,"fix",2925,2940,,-999.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1397,"fix",2940,2955,,-1006.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1398,"fix",2955,2970,,-1013.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1399,"fix",2970,2985,,-1020.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1400,"fix",2985,3000,,-1027.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1401,"fix",3000,3015,,-1035.13,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1402,"fix",3015,3030,,-1042.35,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1403,"fix",3030,3045,,-1049.58,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1404,"fix",3045,3060,,-1056.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1405,"fix",3060,3075,,-1064.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1406,"fix",3075,3090,,-1071.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1407,"fix",3090,3105,,-1078.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1408,"fix",3105,3120,,-1085.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1409,"fix",3120,3135,,-1092.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1410,"fix",3135,3150,,-1100.13,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1411,"fix",3150,3165,,-1107.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1412,"fix",3165,3180,,-1114.58,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1413,"fix",3180,3195,,-1121.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1414,"fix",3195,3210,,-1129.02,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1415,"fix",3210,3225,,-1136.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1416,"fix",3225,3240,,-1143.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1417,"fix",3240,3255,,-1150.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1418,"fix",3255,3270,,-1157.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1419,"fix",3270,3285,,-1165.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1420,"fix",3285,3300,,-1172.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1421,"fix",3300,3315,,-1179.58,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1422,"fix",3315,3330,,-1186.80,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1423,"fix",3330,3345,,-1194.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1424,"fix",3345,3360,,-1201.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1425,"fix",3360,3375,,-1208.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1426,"fix",3375,3390,,-1215.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1427,"fix",3390,3405,,-1222.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1428,"fix",3405,3420,,-1230.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1429,"fix",3420,3435,,-1237.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1430,"fix",3435,3450,,-1244.58,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1431,"fix",3450,3465,,-1251.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1432,"fix",3465,3480,,-1259.03,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1433,"fix",3480,3495,,-1266.25,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1434,"fix",3495,3510,,-1273.47,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1435,"fix",3510,3525,,-1280.70,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1436,"fix",3525,3540,,-1287.92,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1437,"fix",3540,3555,,-1295.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1438,"fix",3555,3570,,-1302.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1439,"fix",3570,3585,,-1309.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1440,"fix",3585,3600,,-1316.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1441,"fix",3600,3615,,-1324.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1442,"fix",3615,3630,,-1332.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1443,"fix",3630,3645,,-1340.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1444,"fix",3645,3660,,-1348.29,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1445,"fix",3660,3675,,-1356.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1446,"fix",3675,3690,,-1364.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1447,"fix",3690,3705,,-1372.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1448,"fix",3705,3720,,-1380.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1449,"fix",3720,3735,,-1388.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1450,"fix",3735,3750,,-1396.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1451,"fix",3750,3765,,-1404.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1452,"fix",3765,3780,,-1412.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1453,"fix",3780,3795,,-1420.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1454,"fix",3795,3810,,-1428.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1455,"fix",3810,3825,,-1436.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1456,"fix",3825,3840,,-1444.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1457,"fix",3840,3855,,-1452.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1458,"fix",3855,3870,,-1460.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1459,"fix",3870,3885,,-1468.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1460,"fix",3885,3900,,-1476.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1461,"fix",3900,3915,,-1484.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1462,"fix",3915,3930,,-1492.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1463,"fix",3930,3945,,-1500.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1464,"fix",3945,3960,,-1508.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1465,"fix",3960,3975,,-1516.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1466,"fix",3975,3990,,-1524.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1467,"fix",3990,4005,,-1532.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1468,"fix",4005,4020,,-1540.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1469,"fix",4020,4035,,-1548.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1470,"fix",4035,4050,,-1556.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1471,"fix",4050,4065,,-1564.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1472,"fix",4065,4080,,-1572.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1473,"fix",4080,4095,,-1581.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1474,"fix",4095,4110,,-1589.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1475,"fix",4110,4125,,-1597.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1476,"fix",4125,4140,,-1605.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1477,"fix",4140,4155,,-1613.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1478,"fix",4155,4170,,-1621.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1479,"fix",4170,4185,,-1629.16,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1480,"fix",4185,4200,,-1637.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1481,"fix",4200,4215,,-1645.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1482,"fix",4215,4230,,-1653.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1483,"fix",4230,4245,,-1661.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1484,"fix",4245,4260,,-1669.29,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1485,"fix",4260,4275,,-1677.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1486,"fix",4275,4290,,-1685.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1487,"fix",4290,4305,,-1693.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1488,"fix",4305,4320,,-1701.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1489,"fix",4320,4335,,-1709.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1490,"fix",4335,4350,,-1717.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1491,"fix",4350,4365,,-1725.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1492,"fix",4365,4380,,-1733.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1493,"fix",4380,4395,,-1741.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1494,"fix",4395,4410,,-1749.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1495,"fix",4410,4425,,-1757.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1496,"fix",4425,4440,,-1765.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1497,"fix",4440,4455,,-1773.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1498,"fix",4455,4470,,-1781.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1499,"fix",4470,4485,,-1789.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1500,"fix",4485,4500,,-1797.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1501,"fix",4500,4515,,-1805.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1502,"fix",4515,4530,,-1813.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1503,"fix",4530,4545,,-1821.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1504,"fix",4545,4560,,-1829.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1505,"fix",4560,4575,,-1837.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1506,"fix",4575,4590,,-1845.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1507,"fix",4590,4605,,-1853.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1508,"fix",4605,4620,,-1861.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1509,"fix",4620,4635,,-1869.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1510,"fix",4635,4650,,-1877.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1511,"fix",4650,4665,,-1885.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1512,"fix",4665,4680,,-1893.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1513,"fix",4680,4695,,-1902.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1514,"fix",4695,4710,,-1910.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1515,"fix",4710,4725,,-1918.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1516,"fix",4725,4740,,-1926.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1517,"fix",4740,4755,,-1934.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1518,"fix",4755,4770,,-1942.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1519,"fix",4770,4785,,-1950.16,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1520,"fix",4785,4800,,-1958.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1521,"fix",4800,4815,,-1966.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1522,"fix",4815,4830,,-1974.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1523,"fix",4830,4845,,-1982.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1524,"fix",4845,4860,,-1990.29,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1525,"fix",4860,4875,,-1998.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1526,"fix",4875,4890,,-2006.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1527,"fix",4890,4905,,-2014.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1528,"fix",4905,4920,,-2022.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1529,"fix",4920,4935,,-2030.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1530,"fix",4935,4950,,-2038.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1531,"fix",4950,4965,,-2046.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1532,"fix",4965,4980,,-2054.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1533,"fix",4980,4995,,-2062.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1534,"fix",4995,5010,,-2070.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1535,"fix",5010,5025,,-2078.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1536,"fix",5025,5040,,-2086.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1537,"fix",5040,5055,,-2094.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1538,"fix",5055,5070,,-2102.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1539,"fix",5070,5085,,-2110.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1540,"fix",5085,5100,,-2118.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1541,"fix",5100,5115,,-2126.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1542,"fix",5115,5130,,-2134.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1543,"fix",5130,5145,,-2142.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1544,"fix",5145,5160,,-2150.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1545,"fix",5160,5175,,-2158.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1546,"fix",5175,5190,,-2166.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1547,"fix",5190,5205,,-2174.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1548,"fix",5205,5220,,-2182.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1549,"fix",5220,5235,,-2190.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1550,"fix",5235,5250,,-2198.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1551,"fix",5250,5265,,-2206.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1552,"fix",5265,5280,,-2214.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1553,"fix",5280,5295,,-2223.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1554,"fix",5295,5310,,-2231.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1555,"fix",5310,5325,,-2239.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1556,"fix",5325,5340,,-2247.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1557,"fix",5340,5355,,-2255.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1558,"fix",5355,5370,,-2263.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1559,"fix",5370,5385,,-2271.16,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1560,"fix",5385,5400,,-2279.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1561,"fix",5400,5415,,-2287.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1562,"fix",5415,5430,,-2295.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1563,"fix",5430,5445,,-2303.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1564,"fix",5445,5460,,-2311.29,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1565,"fix",5460,5475,,-2319.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1566,"fix",5475,5490,,-2327.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1567,"fix",5490,5505,,-2335.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1568,"fix",5505,5520,,-2343.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1569,"fix",5520,5535,,-2351.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1570,"fix",5535,5550,,-2359.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1571,"fix",5550,5565,,-2367.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1572,"fix",5565,5580,,-2375.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1573,"fix",5580,5595,,-2383.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1574,"fix",5595,5610,,-2391.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1575,"fix",5610,5625,,-2399.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1576,"fix",5625,5640,,-2407.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1577,"fix",5640,5655,,-2415.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1578,"fix",5655,5670,,-2423.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1579,"fix",5670,5685,,-2431.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1580,"fix",5685,5700,,-2439.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1581,"fix",5700,5715,,-2447.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1582,"fix",5715,5730,,-2455.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1583,"fix",5730,5745,,-2463.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1584,"fix",5745,5760,,-2471.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1585,"fix",5760,5775,,-2479.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1586,"fix",5775,5790,,-2487.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1587,"fix",5790,5805,,-2495.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1588,"fix",5805,5820,,-2503.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1589,"fix",5820,5835,,-2511.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1590,"fix",5835,5850,,-2519.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1591,"fix",5850,5865,,-2527.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1592,"fix",5865,5880,,-2535.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1593,"fix",5880,5895,,-2544.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1594,"fix",5895,5910,,-2552.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1595,"fix",5910,5925,,-2560.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1596,"fix",5925,5940,,-2568.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1597,"fix",5940,5955,,-2576.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1598,"fix",5955,5970,,-2584.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1599,"fix",5970,5985,,-2592.16,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1600,"fix",5985,6000,,-2600.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1601,"fix",6000,6015,,-2608.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1602,"fix",6015,6030,,-2616.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1603,"fix",6030,6045,,-2624.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1604,"fix",6045,6060,,-2632.29,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1605,"fix",6060,6075,,-2640.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1606,"fix",6075,6090,,-2648.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1607,"fix",6090,6105,,-2656.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1608,"fix",6105,6120,,-2664.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1609,"fix",6120,6135,,-2672.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1610,"fix",6135,6150,,-2680.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1611,"fix",6150,6165,,-2688.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1612,"fix",6165,6180,,-2696.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1613,"fix",6180,6195,,-2704.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1614,"fix",6195,6210,,-2712.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1615,"fix",6210,6225,,-2720.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1616,"fix",6225,6240,,-2728.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1617,"fix",6240,6255,,-2736.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1618,"fix",6255,6270,,-2744.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1619,"fix",6270,6285,,-2752.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1620,"fix",6285,6300,,-2760.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1621,"fix",6300,6315,,-2768.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1622,"fix",6315,6330,,-2776.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1623,"fix",6330,6345,,-2784.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1624,"fix",6345,6360,,-2792.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1625,"fix",6360,6375,,-2800.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1626,"fix",6375,6390,,-2808.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1627,"fix",6390,6405,,-2816.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1628,"fix",6405,6420,,-2824.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1629,"fix",6420,6435,,-2832.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1630,"fix",6435,6450,,-2840.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1631,"fix",6450,6465,,-2848.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1632,"fix",6465,6480,,-2856.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1633,"fix",6480,6495,,-2865.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1634,"fix",6495,6510,,-2873.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1635,"fix",6510,6525,,-2881.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1636,"fix",6525,6540,,-2889.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1637,"fix",6540,6555,,-2897.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1638,"fix",6555,6570,,-2905.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1639,"fix",6570,6585,,-2913.16,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1640,"fix",6585,6600,,-2921.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1641,"fix",6600,6615,,-2929.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1642,"fix",6615,6630,,-2937.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1643,"fix",6630,6645,,-2945.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1644,"fix",6645,6660,,-2953.29,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1645,"fix",6660,6675,,-2961.31,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1646,"fix",6675,6690,,-2969.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1647,"fix",6690,6705,,-2977.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1648,"fix",6705,6720,,-2985.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1649,"fix",6720,6735,,-2993.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1650,"fix",6735,6750,,-3001.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1651,"fix",6750,6765,,-3009.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1652,"fix",6765,6780,,-3017.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1653,"fix",6780,6795,,-3025.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1654,"fix",6795,6810,,-3033.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1655,"fix",6810,6825,,-3041.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1656,"fix",6825,6840,,-3049.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1657,"fix",6840,6855,,-3057.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1658,"fix",6855,6870,,-3065.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1659,"fix",6870,6885,,-3073.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1660,"fix",6885,6900,,-3081.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1661,"fix",6900,6915,,-3089.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1662,"fix",6915,6930,,-3097.74,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1663,"fix",6930,6945,,-3105.76,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1664,"fix",6945,6960,,-3113.79,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1665,"fix",6960,6975,,-3121.81,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1666,"fix",6975,6990,,-3129.84,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1667,"fix",6990,7005,,-3137.86,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1668,"fix",7005,7020,,-3145.89,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1669,"fix",7020,7035,,-3153.91,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1670,"fix",7035,7050,,-3161.94,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1671,"fix",7050,7065,,-3169.96,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1672,"fix",7065,7080,,-3177.99,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1673,"fix",7080,7095,,-3186.01,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1674,"fix",7095,7110,,-3194.04,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1675,"fix",7110,7125,,-3202.06,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1676,"fix",7125,7140,,-3210.09,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1677,"fix",7140,7155,,-3218.11,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1678,"fix",7155,7170,,-3226.14,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1679,"fix",7170,7185,,-3234.16,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1680,"fix",7185,7200,,-3242.19,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1681,"fix",7200,7215,,-3250.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1682,"fix",7215,7230,,-3258.24,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1683,"fix",7230,7245,,-3266.26,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1684,"fix",7245,7260,,-3274.29,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1685,"fix",7260,7275,,-3282.21,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1686,"fix",7275,7290,,-3290.34,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1687,"fix",7290,7305,,-3298.36,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1688,"fix",7305,7320,,-3306.39,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1689,"fix",7320,7335,,-3314.41,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1690,"fix",7335,7350,,-3322.44,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1691,"fix",7350,7365,,-3330.46,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1692,"fix",7365,7380,,-3338.49,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1693,"fix",7380,7395,,-3346.51,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1694,"fix",7395,7410,,-3354.54,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1695,"fix",7410,7425,,-3362.56,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1696,"fix",7425,7440,,-3370.59,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1697,"fix",7440,7455,,-3378.61,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1698,"fix",7455,7470,,-3386.64,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1699,"fix",7470,7485,,-3394.66,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1700,"fix",7485,7500,,-3402.69,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+1701,"fix",7500,2147483647,,-3410.71,,"Withholding Tax","Withholding Tax Grid 2017 (Precompte Professionnel Bareme 2017)",130,"P.P","hr_payroll_rules_baremeIII","range","GROSS",,"contrib_register_pp"
+,,,,,,,,,,,,,,,
+1410,"code",1,1,,,"result = min(35, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1411,"code",2,2,,,"result = min(95, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1412,"code",3,3,,,"result = min(248, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1413,"code",4,4,,,"result = min(454, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1414,"code",5,5,,,"result = min(671, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1415,"code",6,6,,,"result = min(887, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1416,"code",7,7,,,"result = min(1105, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1417,"code",8,8,,,"result = min(1344, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1418,"code",9,9,,,"result = min(1590, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1419,"code",10,10,,,"result = min(1836, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1420,"code",11,11,,,"result = min(2082, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1421,"code",12,12,,,"result = min(2328, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1422,"code",13,13,,,"result = min(2574, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1423,"code",14,14,,,"result = min(2820, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1424,"code",15,15,,,"result = min(3066, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1425,"code",16,16,,,"result = min(3312, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1426,"code",17,17,,,"result = min(3558, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1427,"code",18,18,,,"result = min(3804, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1428,"code",19,19,,,"result = min(4050, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
+1429,"code",20,20,,,"result = min(4296, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))","Child Allowance Belgium","Child Allowance Belgium",142,"Ch.A","hr_payroll_rules_child","range","employee.dependent_children",,
diff --git a/addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml b/addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml
index 4427d6510b8..bd9dd3e55be 100644
--- a/addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml
+++ b/addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml
@@ -279,7 +279,7 @@ elif salary &lt;= 2461.27:
<field name="sequence">140</field>
<field name="amount_select">fix</field>
<field name="condition_select">python</field>
- <field name="condition_python">result = bool(employee.dependent_children)</field>
+ <field name="condition_python">result = bool(employee.dependent_children) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
</record>
<record id="hr_payroll_rules_child" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_child_alw"/>
@@ -296,7 +296,7 @@ elif salary &lt;= 2461.27:
a) Reduction for dependent children</field>
<field name="condition_select">python</field>
- <field name="condition_python">result = bool(employee.dependent_children)</field>
+ <field name="condition_python">result = bool(employee.dependent_children) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
</record>
<record id="hr_salary_rule_other_family_charges_reductions" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_category_family_reductions"/>
diff --git a/addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py b/addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py
index 17436cd10c1..72fbc801345 100644
--- a/addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py
+++ b/addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py
@@ -13,17 +13,22 @@ class HrContract(models.Model):
('company_car', 'Company car'),
('public_transport', 'Public Transport'),
('others', 'Other'),
- ], string="Transport", default='company_car')
+ ], string="Transport", default='company_car',
+ help="Transport mode the employee uses to go to work.")
car_atn = fields.Monetary(string='ATN Company Car')
public_transport_employee_amount = fields.Monetary('Paid by the employee (Monthly)')
- thirteen_month = fields.Monetary(compute='_compute_holidays_advantages', string='13th Month')
- double_holidays = fields.Monetary(compute='_compute_holidays_advantages', string='Double holidays')
+ thirteen_month = fields.Monetary(compute='_compute_holidays_advantages', string='13th Month',
+ help="Yearly gross amount the employee receives as 13th month bonus.")
+ double_holidays = fields.Monetary(compute='_compute_holidays_advantages', string='Double holidays',
+ help="Yearly gross amount the employee receives as double holidays bonus.")
warrant_value_employee = fields.Monetary(compute='_compute_warrants_cost', string="Warrant value for the employee")
# Employer costs fields
final_yearly_costs = fields.Monetary(compute='_compute_final_yearly_costs', readonly=False,
- string='Total Employee Cost', groups="hr.group_hr_manager")
- monthly_yearly_costs = fields.Monetary(compute='_compute_monthly_yearly_costs', string='Monthly Equivalent Cost', readonly=True)
+ string='Total Employee Cost', groups="hr.group_hr_manager",
+ help="Total yearly cost of the employee for the employer.")
+ monthly_yearly_costs = fields.Monetary(compute='_compute_monthly_yearly_costs', string='Monthly Equivalent Cost', readonly=True,
+ help="Total monthly cost of the employee for the employer.")
ucm_insurance = fields.Monetary(compute='_compute_ucm_insurance', string="Social Secretary Costs")
social_security_contributions = fields.Monetary(compute='_compute_social_security_contributions', string="Social Security Contributions")
yearly_cost_before_charges = fields.Monetary(compute='_compute_yearly_cost_before_charges', string="Yearly Costs Before Charges")
@@ -36,19 +41,40 @@ class HrContract(models.Model):
warrants_cost = fields.Monetary(compute='_compute_warrants_cost')
# Advantages
- commission_on_target = fields.Monetary(string="Commission on Target", default=1000)
- fuel_card = fields.Monetary(string="Fuel Card", default=150)
- internet = fields.Monetary(string="Internet", default=38, help="Your internet subscription will be paid up to this amount.")
- representation_fees = fields.Monetary(string="Representation Fees", default=150.0)
- mobile = fields.Monetary(string="Mobile", default=30, help="Your mobile subscription will be paid up to this amount.")
- mobile_plus = fields.Monetary(string="International Communication", default=50, help="Your international mobile subscription will be paid up to this amount.")
- meal_voucher_amount = fields.Monetary(string="Meal Vouchers", default=7.45)
- holidays = fields.Float(string="Holidays", default=20)
+ commission_on_target = fields.Monetary(string="Commission on Target",
+ default=lambda self: self.get_attribute('commission_on_target', 'default_value'),
+ help="Monthly gross amount that the employee receives if the target is reached.")
+ fuel_card = fields.Monetary(string="Fuel Card",
+ default=lambda self: self.get_attribute('fuel_card', 'default_value'),
+ help="Monthly amount the employee receives on his fuel card.")
+ internet = fields.Monetary(string="Internet",
+ default=lambda self: self.get_attribute('internet', 'default_value'),
+ help="The employee's internet subcription will be paid up to this amount.")
+ representation_fees = fields.Monetary(string="Representation Fees",
+ default=lambda self: self.get_attribute('representation_fees', 'default_value'),
+ help="Monthly net amount the employee receives to cover his representation fees.")
+ mobile = fields.Monetary(string="Mobile",
+ default=lambda self: self.get_attribute('mobile', 'default_value'),
+ help="The employee's mobile subscription will be paid up to this amount.")
+ mobile_plus = fields.Monetary(string="International Communication",
+ default=lambda self: self.get_attribute('mobile_plus', 'default_value'),
+ help="The employee's mobile subscription for international communication will be paid up to this amount.")
+ meal_voucher_amount = fields.Monetary(string="Meal Vouchers",
+ default=lambda self: self.get_attribute('meal_voucher_amount', 'default_value'),
+ help="Amount the employee receives in the form of meal vouchers per worked day.")
+ holidays = fields.Float(string="Holidays",
+ default=lambda self: self.get_attribute('holidays', 'default_value'),
+ help="Number of days of paid leaves the employee gets per year.")
+ holidays_editable = fields.Boolean(string="Editable Holidays", default=True)
holidays_compensation = fields.Monetary(compute='_compute_holidays_compensation', string="Holidays Compensation")
wage_with_holidays = fields.Monetary(compute='_compute_wage_with_holidays', sting="Wage update with holidays retenues")
- additional_net_amount = fields.Monetary(string="Net Supplements")
- retained_net_amount = fields.Monetary(sting="Net Retained")
- eco_checks = fields.Monetary("Eco Vouchers", default=250)
+ additional_net_amount = fields.Monetary(string="Net Supplements",
+ help="Monthly net amount the employee receives.")
+ retained_net_amount = fields.Monetary(sting="Net Retained",
+ help="Monthly net amount that is retained on the employee's salary.")
+ eco_checks = fields.Monetary("Eco Vouchers",
+ default=lambda self: self.get_attribute('eco_checks', 'default_value'),
+ help="Yearly amount the employee receives in the form of eco vouchers.")
@api.depends('holidays', 'wage')
def _compute_wage_with_holidays(self):
diff --git a/addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml b/addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml
index b07a075956e..fd7eaa227e5 100644
--- a/addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml
+++ b/addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml
@@ -109,9 +109,10 @@
<field name="double_holidays" nolabel="1"/>
<span>/ year</span>
</div>
+ <field name="holidays_editable"/>
<label for="holidays"/>
<div class="o_row">
- <field name="holidays" nolabel="1"/>
+ <field name="holidays" nolabel="1" attrs="{'readonly': [('holidays_editable', '=', False)]}"/>
<span>/ year</span>
</div>
<field name="holidays_compensation" invisible="1"/>
diff --git a/addons/l10n_be_hr_payroll_fleet/models/fleet.py b/addons/l10n_be_hr_payroll_fleet/models/fleet.py
index b2dffa00667..e70c31ad7f2 100644
--- a/addons/l10n_be_hr_payroll_fleet/models/fleet.py
+++ b/addons/l10n_be_hr_payroll_fleet/models/fleet.py
@@ -11,12 +11,12 @@ from odoo.fields import Datetime
class FleetVehicle(models.Model):
_inherit = 'fleet.vehicle'
- co2_fee = fields.Float(compute='_compute_co2_fee', string="CO2 fee (monthly)")
+ co2_fee = fields.Float(compute='_compute_co2_fee', string="CO2 Fee")
total_depreciated_cost = fields.Float(compute='_compute_total_depreciated_cost',
- string="Total Depreciated Cost", help="This includes all the depreciated costs and the CO2 fee")
+ string="Total Cost (Depreciated)", help="This includes all the depreciated costs and the CO2 fee")
total_cost = fields.Float(compute='_compute_total_cost', string="Total Cost", help="This include all the costs and the CO2 fee")
fuel_type = fields.Selection(required=True, default='diesel')
- atn = fields.Float(compute='_compute_car_atn')
+ atn = fields.Float(compute='_compute_car_atn', string="ATN")
acquisition_date = fields.Date(required=True)
@api.depends('co2_fee', 'log_contracts', 'log_contracts.state', 'log_contracts.recurring_cost_amount_depreciated')
@@ -57,7 +57,7 @@ class FleetVehicle(models.Model):
for car in self:
car.atn = car._get_car_atn(car.acquisition_date, car.car_value, car.fuel_type, car.co2)
- @api.depends('model_id', 'license_plate', 'total_depreciated_cost', 'acquisition_date')
+ @api.depends('model_id', 'license_plate', 'log_contracts', 'total_depreciated_cost', 'acquisition_date')
def _compute_vehicle_name(self):
super(FleetVehicle, self)._compute_vehicle_name()
for vehicle in self:
@@ -116,14 +116,15 @@ class FleetVehicleLogContract(models.Model):
class FleetVehicleModel(models.Model):
_inherit = 'fleet.vehicle.model'
- default_recurring_cost_amount_depreciated = fields.Float(string="Recurring Cost (Depreciated)",
+ default_recurring_cost_amount_depreciated = fields.Float(string="Cost (Depreciated)",
help="Default recurring cost amount that should be applied to a new car from this model")
default_co2 = fields.Float(string="CO2 emissions")
default_fuel_type = fields.Selection([('gasoline', 'Gasoline'), ('diesel', 'Diesel'), ('electric', 'Electric'), ('hybrid', 'Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle')
default_car_value = fields.Float(string="Catalog Value (VAT Incl.)")
can_be_requested = fields.Boolean(string="Can be requested", help="Can be requested on a contract as a new car")
default_atn = fields.Float(compute='_compute_atn', string="ATN")
- default_total_depreciated_cost = fields.Float(compute='_compute_default_total_depreciated_cost')
+ default_total_depreciated_cost = fields.Float(compute='_compute_default_total_depreciated_cost', string="Total Cost (Depreciated)")
+ co2_fee = fields.Float(compute='_compute_co2_fee', string="CO2 fee")
@api.depends('default_car_value', 'default_co2', 'default_fuel_type')
def _compute_atn(self):
@@ -131,10 +132,10 @@ class FleetVehicleModel(models.Model):
for model in self:
model.default_atn = self.env['fleet.vehicle']._get_car_atn(now, model.default_car_value, model.default_fuel_type, model.default_co2)
- @api.depends('default_co2', 'default_recurring_cost_amount_depreciated')
+ @api.depends('co2_fee', 'default_recurring_cost_amount_depreciated')
def _compute_default_total_depreciated_cost(self):
for model in self:
- model.default_total_depreciated_cost = model.default_co2 + model.default_recurring_cost_amount_depreciated
+ model.default_total_depreciated_cost = model.co2_fee + model.default_recurring_cost_amount_depreciated
@api.multi
@api.depends('name', 'brand_id')
@@ -148,3 +149,8 @@ class FleetVehicleModel(models.Model):
else:
new_res.append(res_item)
return new_res
+
+ @api.depends('default_co2')
+ def _compute_co2_fee(self):
+ for model in self:
+ model.co2_fee = self.env['fleet.vehicle']._get_co2_fee(model.default_co2)
diff --git a/addons/l10n_be_hr_payroll_fleet/models/hr_contract.py b/addons/l10n_be_hr_payroll_fleet/models/hr_contract.py
index 4c62264c781..9c13d2a396f 100644
--- a/addons/l10n_be_hr_payroll_fleet/models/hr_contract.py
+++ b/addons/l10n_be_hr_payroll_fleet/models/hr_contract.py
@@ -7,9 +7,10 @@ from odoo import api, fields, models
class HrContract(models.Model):
_inherit = 'hr.contract'
- car_id = fields.Many2one('fleet.vehicle', string='Car',
+ car_id = fields.Many2one('fleet.vehicle', string='Company Car',
domain=lambda self: self._get_available_cars_domain(),
- default=lambda self: self.env['fleet.vehicle'].search([('driver_id', '=', self.employee_id.address_home_id.id)], limit=1))
+ default=lambda self: self.env['fleet.vehicle'].search([('driver_id', '=', self.employee_id.address_home_id.id)], limit=1),
+ help="Employee's company car.")
car_atn = fields.Float(compute='_compute_car_atn_and_costs', string='ATN Company Car')
company_car_total_depreciated_cost = fields.Float(compute='_compute_car_atn_and_costs')
available_cars_amount = fields.Integer(compute='_compute_available_cars_amount', string='Number of available cars')
diff --git a/addons/l10n_be_hr_payroll_fleet/views/fleet_views.xml b/addons/l10n_be_hr_payroll_fleet/views/fleet_views.xml
index 0b9067f29cb..b2496818eb7 100644
--- a/addons/l10n_be_hr_payroll_fleet/views/fleet_views.xml
+++ b/addons/l10n_be_hr_payroll_fleet/views/fleet_views.xml
@@ -5,10 +5,12 @@
<field name="model">fleet.vehicle</field>
<field name="inherit_id" ref="fleet.fleet_vehicle_view_form"/>
<field name="arch" type="xml">
- <xpath expr="//div[@name='co2']" position="after">
- <field name="co2_fee"/>
- </xpath>
<xpath expr="//field[@name='car_value']" position="after">
+ <label for="co2_fee"/>
+ <div class="o_row">
+ <field name="co2_fee"/>
+ <span> / month</span>
+ </div>
<label for="total_depreciated_cost"/>
<div class="o_row">
<field name="total_depreciated_cost" nolabel="1"/>
@@ -47,18 +49,42 @@
</group>
</group>
</xpath>
- <xpath expr="//page[@name='vendors']" position="after">
+ <xpath expr="//page[@name='vendors']" position="before">
<page string="Information">
<group>
- <group>
- <field name="default_car_value"/>
- <field name="default_co2"/>
- <field name="default_fuel_type" widget="selection"/>
- <field name="default_recurring_cost_amount_depreciated"/>
+ <group string="Vehicle Cost">
+ <label for="default_car_value"/>
+ <div class="o_row">
+ <field name="default_car_value" nolabel="1"/>
+ </div>
+ <label for="co2_fee"/>
+ <div class="o_row">
+ <field name="co2_fee" nolabel="1"/>
+ <span> / month</span>
+ </div>
+ <label for="default_recurring_cost_amount_depreciated"/>
+ <div class="o_row">
+ <field name="default_recurring_cost_amount_depreciated" nolabel="1"/>
+ <span> / month</span>
+ </div>
+ <label for="default_total_depreciated_cost"/>
+ <div class="o_row">
+ <field name="default_total_depreciated_cost" nolabel="1"/>
+ <span> / month</span>
+ </div>
+ <label for="default_atn"/>
+ <div class="o_row">
+ <field name="default_atn" nolabel="1"/>
+ <span> / month</span>
+ </div>
</group>
- <group>
- <field name="default_atn"/>
- <field name="default_total_depreciated_cost" invisible="1"/>
+ <group string="Vehicle Information">
+ <label for="default_co2"/>
+ <div class="o_row">
+ <field name="default_co2" nolabel="1"/>
+ <span> g / km</span>
+ </div>
+ <field name="default_fuel_type" widget="selection"/>
</group>
</group>
</page>
diff --git a/addons/l10n_be_hr_payroll_fleet/views/hr_contract_views.xml b/addons/l10n_be_hr_payroll_fleet/views/hr_contract_views.xml
index b88dd91dbc8..4075178b573 100644
--- a/addons/l10n_be_hr_payroll_fleet/views/hr_contract_views.xml
+++ b/addons/l10n_be_hr_payroll_fleet/views/hr_contract_views.xml
@@ -6,19 +6,13 @@
<field name="inherit_id" ref="l10n_be_hr_payroll.hr_contract_view_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='transport_mode']" position="after">
- <label for="car_id" attrs="{'invisible': [('transport_mode', '!=', 'company_car')]}"/>
- <div attrs="{'invisible': [('transport_mode', '!=', 'company_car')]}">
+ <field name="new_car" attrs="{'invisible': ['|', ('transport_mode', '!=', 'company_car'), ('available_cars_amount', '&gt;', 3)]}"/>
+ <label for="car_id" attrs="{'invisible': ['|', ('transport_mode', '!=', 'company_car'), ('new_car', '=', True)]}"/>
+ <div attrs="{'invisible': ['|', ('transport_mode', '!=', 'company_car'), ('new_car', '=', True)]}">
<field name="car_id" nolabel="1" attrs="{'invisible': [('new_car', '=', True)]}"/>
<field name="available_cars_amount" invisible="1"/>
- <div>
- <field name="new_car" attrs="{'invisible': [('available_cars_amount', '&gt;', 3)]}" nolabel="1"/>
- <label for="new_car"/>
- </div>
- <div attrs="{'invisible': [('new_car', '=', False)]}" class="oe_inline">
- <label for="new_car_model_id" class="oe_inline"/>
- <field name="new_car_model_id" class="oe_inline"/>
- </div>
</div>
+ <field name="new_car_model_id" attrs="{'invisible': [('new_car', '=', False)]}"/>
<field name="max_unused_cars" invisible="1"/>
</xpath>
<xpath expr="//field[@name='car_atn']" position="after">
diff --git a/addons/l10n_fr/__manifest__.py b/addons/l10n_fr/__manifest__.py
index fef029afb3d..a9026705999 100644
--- a/addons/l10n_fr/__manifest__.py
+++ b/addons/l10n_fr/__manifest__.py
@@ -30,7 +30,6 @@ configuration of their taxes and fiscal positions manually.
**Credits:** Sistheo, Zeekom, CrysaLEAD, Akretion and Camptocamp.
""",
'depends': ['base_iban', 'account', 'base_vat'],
- 'excludes': ['account_cancel'],
'data': [
'data/l10n_fr_chart_data.xml',
'data/account_chart_template_data.xml',
diff --git a/addons/l10n_fr/data/account_tax_data.xml b/addons/l10n_fr/data/account_tax_data.xml
index b2eee3a6b5e..62b1fd82622 100644
--- a/addons/l10n_fr/data/account_tax_data.xml
+++ b/addons/l10n_fr/data/account_tax_data.xml
@@ -497,7 +497,7 @@
<record model="account.tax.template" id="tva_normale">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 20,0%</field>
- <field name="description">20.0</field>
+ <field name="description">TVA 20%</field>
<field name="amount" eval="20.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445711"/>
@@ -513,7 +513,7 @@
<record model="account.tax.template" id="tva_normale_encaissement">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA à l'encaissement (vente) 20,0%</field>
- <field name="description">20.0</field>
+ <field name="description">TVA à l'encaissement 20%</field>
<field name="amount" eval="20.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445711"/>
@@ -528,7 +528,7 @@
<record model="account.tax.template" id="tva_specifique">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 8,5%</field>
- <field name="description">8.5</field>
+ <field name="description">TVA 8,5%</field>
<field name="amount" eval="8.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445713"/>
@@ -541,7 +541,7 @@
<record model="account.tax.template" id="tva_intermediaire">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 10,0%</field>
- <field name="description">10.0</field>
+ <field name="description">TVA 10%</field>
<field name="amount" eval="10.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445712"/>
@@ -554,7 +554,7 @@
<record model="account.tax.template" id="tva_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 5,5%</field>
- <field name="description">5.5</field>
+ <field name="description">TVA 5,5%</field>
<field name="amount" eval="5.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445713"/>
@@ -567,7 +567,7 @@
<record model="account.tax.template" id="tva_reduite_encaissement">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA réduite à l'encaissement (vente) 5.5%</field>
- <field name="description">5.5</field>
+ <field name="description">TVA réduite à l'encaissement 5,5%</field>
<field name="amount" eval="5.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445713"/>
@@ -582,7 +582,7 @@
<record model="account.tax.template" id="tva_super_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 2,1%</field>
- <field name="description">2.1</field>
+ <field name="description">TVA 2,1%</field>
<field name="amount" eval="2.1"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445713"/>
@@ -595,7 +595,7 @@
<record model="account.tax.template" id="tva_super_reduite_encaissement">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA réduite à l'encaissement (vente) 2.1%</field>
- <field name="description">2.1</field>
+ <field name="description">TVA réduite à l'encaissement 2,1%</field>
<field name="amount" eval="2.1"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445713"/>
@@ -612,7 +612,7 @@
<record model="account.tax.template" id="tva_normale_ttc">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 20,0% TTC</field>
- <field name="description">20.0-TTC</field>
+ <field name="description">TVA 20% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="20.0"/>
<field name="amount_type">percent</field>
@@ -626,7 +626,7 @@
<record model="account.tax.template" id="tva_normale_encaissement_ttc">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA à l'encaissement (vente) 20,0% TTC</field>
- <field name="description">20.0-TTC</field>
+ <field name="description">TVA 20% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="20"/>
<field name="amount_type">percent</field>
@@ -642,7 +642,7 @@
<record model="account.tax.template" id="tva_specifique_ttc">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 8,5% TTC</field>
- <field name="description">8.5-TTC</field>
+ <field name="description">TVA 8,5% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="8.5"/>
<field name="amount_type">percent</field>
@@ -656,7 +656,7 @@
<record model="account.tax.template" id="tva_intermediaire_ttc">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 10,0% TTC</field>
- <field name="description">10.0-TTC</field>
+ <field name="description">TVA 10% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="10.0"/>
<field name="amount_type">percent</field>
@@ -670,7 +670,7 @@
<record model="account.tax.template" id="tva_reduite_ttc">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 5,5% TTC</field>
- <field name="description">5.5-TTC</field>
+ <field name="description">TVA 5,5% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="5.5"/>
<field name="amount_type">percent</field>
@@ -684,7 +684,7 @@
<record model="account.tax.template" id="tva_reduite_encaissement_ttc">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA réduite à l'encaissement (vente) 5.5% TTC</field>
- <field name="description">5.5-TTC</field>
+ <field name="description">TVA réduite à l'encaissement 5,5% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="5.5"/>
<field name="amount_type">percent</field>
@@ -700,7 +700,7 @@
<record model="account.tax.template" id="tva_super_reduite_ttc">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA collectée (vente) 2,1% TTC</field>
- <field name="description">2.1-TTC</field>
+ <field name="description">TVA 2,1% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="2.1"/>
<field name="amount_type">percent</field>
@@ -714,7 +714,7 @@
<record model="account.tax.template" id="tva_super_reduite_encaissement_ttc">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA réduite à l'encaissement (vente) 2.1% TTC</field>
- <field name="description">2.1-TTC</field>
+ <field name="description">TVA réduite à l'encaissement 2,1% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="2.1"/>
<field name="amount_type">percent</field>
@@ -731,7 +731,7 @@
<record model="account.tax.template" id="tva_acq_normale">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 20,0%</field>
- <field name="description">ACH-20.0</field>
+ <field name="description">TVA 20%</field>
<field name="amount" eval="20.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44566"/>
@@ -747,7 +747,7 @@
<record model="account.tax.template" id="tva_acq_specifique">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 8,5%</field>
- <field name="description">ACH-8.5</field>
+ <field name="description">TVA 8,5%</field>
<field name="amount" eval="8.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44566"/>
@@ -760,7 +760,7 @@
<record model="account.tax.template" id="tva_acq_intermediaire">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 10,0%</field>
- <field name="description">ACH-10.0</field>
+ <field name="description">TVA 10%</field>
<field name="amount" eval="10.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44566"/>
@@ -773,7 +773,7 @@
<record model="account.tax.template" id="tva_acq_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 5,5%</field>
- <field name="description">ACH-5.5</field>
+ <field name="description">TVA 5,5%</field>
<field name="amount" eval="5.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44566"/>
@@ -786,7 +786,7 @@
<record model="account.tax.template" id="tva_acq_super_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 2,1%</field>
- <field name="description">ACH-2.1</field>
+ <field name="description">TVA 2,1%</field>
<field name="amount" eval="2.1"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44566"/>
@@ -801,7 +801,7 @@
<record model="account.tax.template" id="tva_acq_normale_TTC">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 20,0% TTC</field>
- <field name="description">ACH-20.0-TTC</field>
+ <field name="description">TVA 20% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="20.0"/>
<field name="amount_type">percent</field>
@@ -815,7 +815,7 @@
<record model="account.tax.template" id="tva_acq_specifique_TTC">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 8,5% TTC</field>
- <field name="description">ACH-8.5-TTC</field>
+ <field name="description">TVA 8,5% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="8.5"/>
<field name="amount_type">percent</field>
@@ -829,7 +829,7 @@
<record model="account.tax.template" id="tva_acq_intermediaire_TTC">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 10,0% TTC</field>
- <field name="description">ACH-10.0-TTC</field>
+ <field name="description">TVA 10% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="10.0"/>
<field name="amount_type">percent</field>
@@ -843,7 +843,7 @@
<record model="account.tax.template" id="tva_acq_reduite_TTC">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 5,5% TTC</field>
- <field name="description">ACH-5.5-TTC</field>
+ <field name="description">TVA 5,5% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="5.5"/>
<field name="amount_type">percent</field>
@@ -857,7 +857,7 @@
<record model="account.tax.template" id="tva_acq_super_reduite_TTC">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déductible (achat) 2,1% TTC</field>
- <field name="description">ACH-2.1-TTC</field>
+ <field name="description">TVA 2,1% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="2.1"/>
<field name="amount_type">percent</field>
@@ -874,7 +874,7 @@
<record model="account.tax.template" id="tva_imm_normale">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd./immobilisation (achat) 20,0%</field>
- <field name="description">IMMO-20.0</field>
+ <field name="description">TVA immo 20%</field>
<field name="amount" eval="20.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44562"/>
@@ -887,7 +887,7 @@
<record model="account.tax.template" id="tva_imm_specifique">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd./immobilisation (achat) 8,5%</field>
- <field name="description">IMMO-8.5</field>
+ <field name="description">TVA immo 8,5%</field>
<field name="amount" eval="8.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44562"/>
@@ -900,7 +900,7 @@
<record model="account.tax.template" id="tva_imm_intermediaire">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd./immobilisation (achat) 10,0%</field>
- <field name="description">IMMO-10.0</field>
+ <field name="description">TVA immo 10%</field>
<field name="amount" eval="10.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44562"/>
@@ -913,7 +913,7 @@
<record model="account.tax.template" id="tva_imm_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd./immobilisation (achat) 5,5%</field>
- <field name="description">IMMO-5.5</field>
+ <field name="description">TVA immo 5,5%</field>
<field name="amount" eval="5.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44562"/>
@@ -926,7 +926,7 @@
<record model="account.tax.template" id="tva_imm_super_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd./immobilisation (achat) 2,1%</field>
- <field name="description">IMMO-2.1</field>
+ <field name="description">TVA immo 2,1%</field>
<field name="amount" eval="2.1"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_44562"/>
@@ -941,7 +941,7 @@
<record model="account.tax.template" id="tva_intra_normale">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA due s/ acq. intracommunautaire (achat) 20,0%</field> <!-- ventes -->
- <field name="description">ACH_UE_due-20.0</field>
+ <field name="description">TVA 20% EU</field>
<field name="amount" eval="-20.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445201"/>
@@ -954,7 +954,7 @@
<record model="account.tax.template" id="tva_intra_specifique">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA due s/ acq. intracommunautaire (achat) 8,5%</field>
- <field name="description">ACH_UE_due-8.5</field>
+ <field name="description">TVA 8,5% EU</field>
<field name="amount" eval="-8.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445203"/>
@@ -967,7 +967,7 @@
<record model="account.tax.template" id="tva_intra_intermediaire">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA due s/ acq. intracommunautaire (achat) 10,0%</field>
- <field name="description">ACH_UE_due-10.0</field>
+ <field name="description">TVA 10% EU</field>
<field name="amount" eval="-10.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445202"/>
@@ -980,7 +980,7 @@
<record model="account.tax.template" id="tva_intra_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA due s/ acq. intracommunautaire (achat) 5,5%</field>
- <field name="description">ACH_UE_due-5.5</field>
+ <field name="description">TVA 5,5% EU</field>
<field name="amount" eval="-5.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445203"/>
@@ -993,7 +993,7 @@
<record model="account.tax.template" id="tva_intra_super_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA due s/ acq. intracommunautaire (achat) 2,1%</field>
- <field name="description">ACH_UE_due-2.1</field>
+ <field name="description">TVA 2,1% EU</field>
<field name="amount" eval="-2.1"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445203"/>
@@ -1008,7 +1008,7 @@
<record model="account.tax.template" id="tva_acq_intra_normale">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd. s/ acq. intracommunautaire (achat) 20,0%</field>
- <field name="description">ACH_UE_ded.-20.0</field>
+ <field name="description">TVA 20% EU</field>
<field name="amount" eval="20.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445662"/>
@@ -1021,7 +1021,7 @@
<record model="account.tax.template" id="tva_acq_intra_specifique">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd. s/ acq. intracommunautaire (achat) 8,5%</field>
- <field name="description">ACH_UE_ded.-8.5</field>
+ <field name="description">TVA 8,5% EU</field>
<field name="amount" eval="8.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445662"/>
@@ -1034,7 +1034,7 @@
<record model="account.tax.template" id="tva_acq_intra_intermediaire">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd. s/ acq. intracommunautaire (achat) 10,0%</field>
- <field name="description">ACH_UE_ded.-10.0</field>
+ <field name="description">TVA 10% EU</field>
<field name="amount" eval="10.0"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445662"/>
@@ -1047,7 +1047,7 @@
<record model="account.tax.template" id="tva_acq_intra_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd. s/ acq. intracommunautaire (achat) 5,5%</field>
- <field name="description">ACH_UE_ded.-5.5</field>
+ <field name="description">TVA 5,5% EU</field>
<field name="amount" eval="5.5"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445662"/>
@@ -1060,7 +1060,7 @@
<record model="account.tax.template" id="tva_acq_intra_super_reduite">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA déd. s/ acq. intracommunautaire (achat) 2,1%</field>
- <field name="description">ACH_UE_ded.-2.1</field>
+ <field name="description">TVA 2,1% EU</field>
<field name="amount" eval="2.1"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445662"/>
@@ -1075,7 +1075,7 @@
<record model="account.tax.template" id="tva_0">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA 0% autres opérations non imposables (vente)</field>
- <field name="description">EXO-0</field>
+ <field name="description">TVA 0%</field>
<field name="amount" eval="0.00"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" eval="False"/>
@@ -1088,7 +1088,7 @@
<record model="account.tax.template" id="tva_export_0">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA 0% export (vente)</field>
- <field name="description">EXPORT-0</field>
+ <field name="description">TVA 0% Import</field>
<field name="amount" eval="0.00"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" eval="False"/>
@@ -1101,7 +1101,7 @@
<record model="account.tax.template" id="tva_intra_0">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA 0% livraisons intracommunautaires (vente)</field>
- <field name="description">UE-0</field>
+ <field name="description">TVA 0% EU</field>
<field name="amount" eval="0.00"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445201"/>
@@ -1114,7 +1114,7 @@
<record model="account.tax.template" id="tva_import_0">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
<field name="name">TVA 0% import (achat)</field>
- <field name="description">IMPORT-0</field>
+ <field name="description">TVA 0% Import</field>
<field name="amount" eval="0.00"/>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="pcg_445663"/>
diff --git a/addons/l10n_fr_hr_payroll/report/report_l10n_fr_fiche_paye.xml b/addons/l10n_fr_hr_payroll/report/report_l10n_fr_fiche_paye.xml
index e8f0799bcbc..56a7e28210e 100644
--- a/addons/l10n_fr_hr_payroll/report/report_l10n_fr_fiche_paye.xml
+++ b/addons/l10n_fr_hr_payroll/report/report_l10n_fr_fiche_paye.xml
@@ -48,7 +48,7 @@
</td>
<td>
<span t-esc="o.employee_id.id or '_'"/><br/>
- <span t-esc="o.employee_id.ssnid or '_'"/><br/>
+ <span t-esc="o.employee_id.identification_id or '_'"/><br/>
<span t-esc="o.contract_id.job_id.name or '_'"/><br/>
<span t-esc="o.contract_id.qualif or '_'"/><br/>
<span t-esc="o.contract_id.niveau or '_'"/><br/>
diff --git a/addons/mail/static/src/js/composer.js b/addons/mail/static/src/js/composer.js
index edfb78f00db..965545e3f8d 100644
--- a/addons/mail/static/src/js/composer.js
+++ b/addons/mail/static/src/js/composer.js
@@ -347,7 +347,6 @@ var MentionManager = Widget.extend({
var BasicComposer = Widget.extend(chat_mixin, {
template: "mail.ChatComposer",
-
events: {
"keydown .o_composer_input textarea": "on_keydown",
"keyup .o_composer_input": "on_keyup",
@@ -356,6 +355,8 @@ var BasicComposer = Widget.extend(chat_mixin, {
"click .o_composer_button_add_attachment": "on_click_add_attachment",
"click .o_attachment_delete": "on_attachment_delete",
},
+ // RPCs done to fetch the mention suggestions are throttled with the following value
+ MENTION_THROTTLE: 200,
init: function (parent, options) {
this._super.apply(this, arguments);
@@ -670,7 +671,7 @@ var BasicComposer = Widget.extend(chat_mixin, {
.then(function (results) {
def.resolve(results);
});
- }, 200);
+ }, this.MENTION_THROTTLE);
return def;
},
mention_fetch_channels: function (search) {
@@ -704,7 +705,7 @@ var BasicComposer = Widget.extend(chat_mixin, {
});
if (!suggestions.length && !self.options.mention_partners_restricted) {
// no result found among prefetched partners, fetch other suggestions
- suggestions = mention_fetch_throttled('res.partner', 'get_mention_suggestions', {
+ suggestions = self.mention_fetch_throttled('res.partner', 'get_mention_suggestions', {
limit: limit,
search: search,
});
diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js
index 7e90a3fbec8..f55e247a5b6 100644
--- a/addons/mail/static/tests/chatter_tests.js
+++ b/addons/mail/static/tests/chatter_tests.js
@@ -1,11 +1,16 @@
odoo.define('mail.chatter_tests', function (require) {
"use strict";
+var Composers = require('mail.composer');
+
var Bus = require('web.Bus');
+var concurrency = require('web.concurrency');
var FormView = require('web.FormView');
var KanbanView = require('web.KanbanView');
var testUtils = require('web.test_utils');
+var BasicComposer = Composers.BasicComposer;
+
var createView = testUtils.createView;
QUnit.module('mail', {}, function () {
@@ -318,7 +323,12 @@ QUnit.test('kanban activity widget with an activity', function (assert) {
});
QUnit.test('chatter: post, receive and star messages', function (assert) {
- assert.expect(22);
+ var done = assert.async();
+ assert.expect(27);
+
+ // Remove the mention throttle to speed up the test
+ var mentionThrottle = BasicComposer.prototype.MENTION_THROTTLE;
+ BasicComposer.prototype.MENTION_THROTTLE = 1;
this.data.partner.records[0].message_ids = [1];
var messages = [{
@@ -334,6 +344,7 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
res_id: 2,
}];
var bus = new Bus();
+ var getSuggestionsDef = $.Deferred();
var form = createView({
View: FormView,
model: 'partner',
@@ -348,9 +359,13 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
'</form>',
res_id: 2,
mockRPC: function (route, args) {
- if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") {
+ if (args.method === 'message_get_suggested_recipients') {
return $.when({2: []});
}
+ if (args.method === 'get_mention_suggestions') {
+ getSuggestionsDef.resolve();
+ return $.when([{email: "test@odoo.com", id: 1, name: "Test User"}]);
+ }
return this._super(route, args);
},
session: {},
@@ -447,7 +462,35 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
form.$('.o_thread_message[data-message-id=2] .o_thread_message_star').click();
assert.ok(form.$('.o_thread_message[data-message-id=2] .o_thread_message_star.fa-star-o').length,
"message 2 should not be starred");
- form.destroy();
+
+ // very basic test of mention
+ form.$('.o_chatter_button_new_message').click();
+ var $input = form.$('.oe_chatter .o_composer_text_field:first()');
+ $input.val('@');
+ // the cursor position must be set for the mention manager to detect that we are mentionning
+ $input[0].selectionStart = 1;
+ $input[0].selectionEnd = 1;
+ $input.trigger('keyup');
+
+ assert.strictEqual(getSuggestionsDef.state(), "pending",
+ "the mention suggestion RPC should be throttled");
+
+ getSuggestionsDef
+ .then(concurrency.delay.bind(concurrency, 0))
+ .then(function () {
+ assert.strictEqual(form.$('.o_mention_proposition:visible').length, 1,
+ "there should be one mention suggestion");
+ assert.strictEqual(form.$('.o_mention_proposition').data('id'), 1,
+ "suggestion's id should be correct");
+ assert.strictEqual(form.$('.o_mention_proposition .o_mention_name').text(), 'Test User',
+ "suggestion should be displayed correctly");
+ assert.strictEqual(form.$('.o_mention_proposition .o_mention_info').text(), '(test@odoo.com)',
+ "suggestion should be displayed correctly");
+
+ BasicComposer.prototype.MENTION_THROTTLE = mentionThrottle;
+ form.destroy();
+ done();
+ });
});
QUnit.test('form activity widget: schedule next activity', function (assert) {
diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py
index 8a683be0994..633a11e1e74 100644
--- a/addons/mass_mailing/models/mass_mailing.py
+++ b/addons/mass_mailing/models/mass_mailing.py
@@ -507,7 +507,7 @@ class MassMailing(models.Model):
return super(MassMailing, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby)
def update_opt_out(self, email, res_ids, value):
- model = self.env[self.mailing_model_real]
+ model = self.env[self.mailing_model_real].with_context(active_test=False)
if 'opt_out' in model._fields:
email_fname = 'email_from'
if 'email' in model._fields:
diff --git a/addons/mass_mailing/static/src/js/mass_mailing_editor.js b/addons/mass_mailing/static/src/js/mass_mailing_editor.js
index 4475d001e5d..5d475808589 100644
--- a/addons/mass_mailing/static/src/js/mass_mailing_editor.js
+++ b/addons/mass_mailing/static/src/js/mass_mailing_editor.js
@@ -273,9 +273,13 @@ snippets_editor.Class.include({
function editable_area_is_empty($layout) {
$layout = $layout || $editable_area.find(".o_layout");
var $mail_wrapper = $layout.children(".o_mail_wrapper");
+ var $mail_wrapper_content = $mail_wrapper.find('.o_mail_wrapper_td');
+ if (!$mail_wrapper_content.length) { // compatibility
+ $mail_wrapper_content = $mail_wrapper;
+ }
return (
$editable_area.html().trim() === ""
- || ($layout.length > 0 && ($layout.html().trim() === "" || $mail_wrapper.length > 0 && $mail_wrapper.html().trim() === ""))
+ || ($layout.length > 0 && ($layout.html().trim() === "" || $mail_wrapper_content.length > 0 && $mail_wrapper_content.html().trim() === ""))
);
}
@@ -325,7 +329,15 @@ snippets_editor.Class.include({
switch_images(theme_params, $editable_area);
var $old_layout = $editable_area.find(".o_layout");
- var $new_wrapper = $("<div/>", {"class": "o_mail_wrapper oe_structure"});
+ // This wrapper structure is the only way to have a responsive and
+ // centered fixed-width content column on all mail clients
+ var $new_wrapper = $('<table/>', {class: 'o_mail_wrapper'});
+ var $new_wrapper_content = $("<td/>", {class: 'o_mail_no_resize o_mail_wrapper_td oe_structure'});
+ $new_wrapper.append($('<tr/>').append(
+ $("<td/>", {class: 'o_mail_no_resize'}),
+ $new_wrapper_content,
+ $("<td/>", {class: 'o_mail_no_resize'})
+ ));
var $new_layout = $("<div/>", {"class": "o_layout " + theme_params.className}).append($new_wrapper);
var $contents;
@@ -338,11 +350,11 @@ snippets_editor.Class.include({
}
$editable_area.empty().append($new_layout);
- $new_wrapper.append($contents);
+ $new_wrapper_content.append($contents);
$old_layout.remove();
if (first_choice) {
- self.add_default_snippet_text_classes($new_wrapper);
+ self.add_default_snippet_text_classes($new_wrapper_content);
}
self.show_blocks();
}
diff --git a/addons/mass_mailing/static/src/less/themes/theme_default.less b/addons/mass_mailing/static/src/less/themes/theme_default.less
index 98f86421000..74f71191db2 100644
--- a/addons/mass_mailing/static/src/less/themes/theme_default.less
+++ b/addons/mass_mailing/static/src/less/themes/theme_default.less
@@ -49,27 +49,36 @@
// ===== Layout =====
.o_layout {
- font-family: @o_mm_def_font;
- color: lighten(@o_mm_def_text_color, 20%);
overflow: hidden;
- width: 100%;
+ width: 94%;
min-height: 100%;
background-color: @o_mm_def_color_alpha;
- padding: 24px 0;
+ padding: 24px 3%;
+
+ // Forces on <p/> elements as several mail clients does not correctly
+ // inherit font properties
+ &, p {
+ font-family: @o_mm_def_font;
+ color: lighten(@o_mm_def_text_color, 20%);
+ }
> .o_mail_wrapper {
width: 100%;
- max-width: @o_mm_def_body_width;
- margin: auto;
- border: 1px solid darken(@o_mm_def_color_alpha, 2%);
- background-color: @o_mm_def_color_beta;
+ border-collapse: separate; // Allow the first and last td to have the
+ // same width
+
+ .o_mail_wrapper_td {
+ width: @o_mm_def_body_width;
+ border: 1px solid darken(@o_mm_def_color_alpha, 2%);
+ background-color: @o_mm_def_color_beta;
+ }
}
}
// ===== Snippets (general) =====
.o_mail_snippet_general {
width: 100%;
- max-width: @o_mm_def_body_width;
+ max-width: @o_mm_def_body_width; // should not be necessary thanks to mail wrapper
margin: 0 auto;
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
@@ -157,7 +166,11 @@
}
.o_mail_block_two_cols, .o_mail_block_three_cols {
- font-size: small;
+ // Forces on <p/> elements as several mail clients does not correctly
+ // inherit font properties
+ &, p {
+ font-size: small;
+ }
.o_mail_col_container {
padding: 10px 20px;
@@ -169,7 +182,11 @@
}
.o_mail_block_image_text, .o_mail_block_text_image {
- font-size: small;
+ // Forces on <p/> elements as several mail clients does not correctly
+ // inherit font properties
+ &, p {
+ font-size: small;
+ }
}
.o_mail_block_event {
diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py
index 5fd40f455c7..ac799bd0538 100644
--- a/addons/mrp/models/mrp_production.py
+++ b/addons/mrp/models/mrp_production.py
@@ -499,11 +499,14 @@ class MrpProduction(models.Model):
@api.multi
def post_inventory(self):
for order in self:
+ moves_not_to_do = order.move_raw_ids.filtered(lambda x: x.state == 'done')
moves_to_do = order.move_raw_ids.filtered(lambda x: x.state not in ('done', 'cancel'))
moves_to_do.action_done()
+ moves_to_do = order.move_raw_ids.filtered(lambda x: x.state == 'done') - moves_not_to_do
order._cal_price(moves_to_do)
moves_to_finish = order.move_finished_ids.filtered(lambda x: x.state not in ('done','cancel'))
moves_to_finish.action_done()
+
for move in moves_to_finish:
#Group quants by lots
lot_quants = {}
diff --git a/addons/mrp/static/tests/mrp_tests.js b/addons/mrp/static/tests/mrp_tests.js
index 3d94c2d1ca3..ed4dab4f91b 100644
--- a/addons/mrp/static/tests/mrp_tests.js
+++ b/addons/mrp/static/tests/mrp_tests.js
@@ -77,8 +77,8 @@ QUnit.module('mrp', {
"there should not be a any visible 'Upload' button");
assert.notOk(form.$('.o_field_widget iframe.o_pdfview_iframe').hasClass('o_hidden'),
"there should be an visible iframe");
- assert.strictEqual(form.$('.o_field_widget iframe.o_pdfview_iframe').attr('src'),
- '#test:/web/static/lib/pdfjs/web/viewer.html?file=%2Fweb%2Fimage%3Fmodel%3Dpartner%26field%3Ddocument%26id%3D1',
+ assert.strictEqual(form.$('.o_field_widget iframe.o_pdfview_iframe').attr('data-src'),
+ '/web/static/lib/pdfjs/web/viewer.html?file=%2Fweb%2Fimage%3Fmodel%3Dpartner%26field%3Ddocument%26id%3D1',
"the src attribute should be correctly set on the iframe");
form.destroy();
diff --git a/addons/pad/static/src/js/pad.js b/addons/pad/static/src/js/pad.js
index 8fb09df0173..76f6ad9b9ae 100644
--- a/addons/pad/static/src/js/pad.js
+++ b/addons/pad/static/src/js/pad.js
@@ -3,116 +3,167 @@ odoo.define('pad.pad', function (require) {
var AbstractField = require('web.AbstractField');
var core = require('web.core');
-var field_registry = require('web.field_registry');
+var fieldRegistry = require('web.field_registry');
var _t = core._t;
-
var FieldPad = AbstractField.extend({
template: 'FieldPad',
content: "",
events: {
- 'click .oe_pad_switch': function() {
- this.$el.toggleClass('oe_pad_fullscreen mb0');
- this.$('.oe_pad_switch').toggleClass('fa-expand fa-compress');
- },
+ 'click .oe_pad_switch': '_onToggleFullScreen',
},
supportedFieldTypes: ['char'],
- init: function() {
- var self = this;
- this._super.apply(this, arguments);
- this.configured = false;
- this._configured_deferred = $.Deferred();
- this._url_request_deferred = $.Deferred();
+ /**
+ * @override
+ */
+ willStart: function () {
+ if (this.isPadConfigured === undefined) {
+ return this._rpc({
+ method: 'pad_is_configured',
+ model: this.model,
+ }).then(function (result) {
+ // we write on the prototype to share the information between
+ // all pad widgets instances, across all actions
+ FieldPad.prototype.isPadConfigured = result;
+ });
+ }
+ return $.when();
+ },
+ /**
+ * @override
+ */
+ start: function () {
+ if (!this.isPadConfigured) {
+ this.$(".oe_unconfigured").removeClass('hidden');
+ this.$(".oe_configured").addClass('hidden');
+ return;
+ }
+ return this._super.apply(this, arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
- this.trigger_up('perform_model_rpc', {
- method: 'pad_is_configured',
- model: this.model,
- on_success: function (data) {
- self.set_configured(!!data);
- self._configured_deferred.resolve();
- },
- on_fail: function () {
- self.set_configured(true);
- self._configured_deferred.resolve();
- },
- });
+ /**
+ * If we had to generate an url, we wait for the generation to be completed,
+ * so the current record will be associated with the correct pad url.
+ *
+ * @override
+ */
+ commitChanges: function () {
+ return this.urlDef;
},
- render_readonly: function() {
- var self = this;
- this._configured_deferred.then(function() {
- if (self.configured){
- if (_.str.startsWith(self.value, 'http')) {
- self.trigger_up('perform_model_rpc', {
- method: 'pad_get_content',
- model: self.model,
- args: [self.value],
- on_success: function(data) {
- self.$('.oe_pad_content').removeClass('oe_pad_loading').html('<div class="oe_pad_readonly"><div>');
- self.$('.oe_pad_readonly').html(data);
- },
- on_fail: function() {
- self.$('.oe_pad_content').text(_t('Unable to load pad'));
- }
- });
- } else {
- self.$('.oe_pad_content').addClass('oe_pad_loading').show().text(_t("This pad will be initialized on first edit"));
- }
- }
- });
+ /**
+ * @override
+ */
+ isSet: function () {
+ return true;
},
- render_edit: function() {
- var self = this;
- this._configured_deferred.then(function() {
- if (! self.value || !_.str.startsWith(self.value, 'http')) {
- self.trigger_up('perform_model_rpc', {
- method: 'pad_generate_url',
- model: self.model,
- context: {
- model: self.model,
- field_name: self.name,
- object_id: self.model
- },
- on_success: function(data) {
- if (! data.url) {
- self.set_configured(false);
- } else {
- self.set_value(data.url);
- }
- self._url_request_deferred.resolve();
- },
- });
- } else {
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Note that this method has some serious side effects: performing rpcs and
+ * setting the value of this field. This is not conventional and should not
+ * be copied in other code, unless really necessary.
+ *
+ * @override
+ * @private
+ */
+ _renderEdit: function () {
+ if (_.str.startsWith(this.value, 'http')) {
+ // here, we have a valid url, so we can simply display an iframe
+ // with the correct src attribute
+ var userName = encodeURIComponent(this.getSession().userName);
+ var url = this.value + '?showChat=false&userName=' + userName;
+ var content = '<iframe width="100%" height="100%" frameborder="0" src="' + url + '"></iframe>';
+ this.$('.oe_pad_content').html(content);
+ } else if (this.value) {
+ // it looks like the field does not contain a valid url, so we just
+ // display it (it cannot be edited in that case)
+ this.$('.oe_pad_content').text(this.value);
+ } else {
+ // It is totally discouraged to have a render method that does
+ // non-rendering work, especially since the work in question
+ // involves doing RPCs and changing the value of the field.
+ // However, this is kind of necessary in this case, because the
+ // value of the field is actually only the url of the pad. The
+ // actual content will be loaded in an iframe. We could do this
+ // work in the basic model, but the basic model does not know that
+ // this widget is in edit or readonly, and we really do not want to
+ // create a pad url everytime a task without a pad is viewed.
+ var self = this;
+ this.urlDef = this._rpc({
+ method: 'pad_generate_url',
+ model: this.model,
+ context: {
+ model: this.model,
+ field_name: this.name,
+ object_id: this.res_id
+ },
+ }, {
+ shadow: true
+ }).then(function (result) {
// We need to write the url of the pad to trigger
// the write function which updates the actual value
// of the field to the value of the pad content
- self.set_value(self.value);
- self._url_request_deferred.resolve();
- }
- self._url_request_deferred.then(function() {
- if (_.str.startsWith(self.value, 'http')) {
- var content = '<iframe width="100%" height="100%" frameborder="0" src="' + self.value + '?showChat=false&userName=' + encodeURIComponent(self.session.username) + '"></iframe>';
- self.$('.oe_pad_content').html(content);
- }
- else {
- self.$('.oe_pad_content').text(self.value);
- }
+ self._setValue(result.url);
});
- });
+ }
},
- set_configured: function(configured) {
- this.configured = configured;
- if (!configured) {
- this.$(".oe_unconfigured").removeClass('hidden');
- this.$(".oe_configured").addClass('hidden');
+ /**
+ * @override
+ * @private
+ */
+ _renderReadonly: function () {
+ if (_.str.startsWith(this.value, 'http')) {
+ var self = this;
+ this.$('.oe_pad_content')
+ .addClass('oe_pad_loading')
+ .text(_t("Loading"));
+ this._rpc({
+ method: 'pad_get_content',
+ model: this.model,
+ args: [this.value]
+ }, {
+ shadow: true
+ }).then(function (data) {
+ self.$('.oe_pad_content')
+ .removeClass('oe_pad_loading')
+ .html('<div class="oe_pad_readonly"><div>');
+ self.$('.oe_pad_readonly').html(data);
+ }).fail(function () {
+ self.$('.oe_pad_content').text(_t('Unable to load pad'));
+ });
+ } else {
+ this.$('.oe_pad_content')
+ .addClass('oe_pad_loading')
+ .show()
+ .text(_t("This pad will be initialized on first edit"));
}
},
- is_set: function() {
- return true;
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ * @private
+ */
+ _onToggleFullScreen: function () {
+ this.$el.toggleClass('oe_pad_fullscreen mb0');
+ this.$('.oe_pad_switch').toggleClass('fa-expand fa-compress');
},
});
-field_registry.add('pad', FieldPad);
+fieldRegistry.add('pad', FieldPad);
+
+return FieldPad;
});
diff --git a/addons/pad/static/tests/pad_tests.js b/addons/pad/static/tests/pad_tests.js
new file mode 100644
index 00000000000..69342f5de6e
--- /dev/null
+++ b/addons/pad/static/tests/pad_tests.js
@@ -0,0 +1,151 @@
+odoo.define('pad.pad_tests', function (require) {
+"use strict";
+
+var FieldPad = require('pad.pad');
+var FormView = require('web.FormView');
+var testUtils = require('web.test_utils');
+
+var createView = testUtils.createView;
+
+QUnit.module('pad widget', {
+ beforeEach: function () {
+ this.data = {
+ task: {
+ fields: {
+ description: {string: "Description", type: "char"},
+ },
+ records: [
+ {id: 1, description: false},
+ {id: 2, description: "https://pad.odoo.pad/p/test-03AK6RCJT"},
+ ],
+ pad_is_configured: function () {
+ return true;
+ },
+ pad_generate_url: function (route, args) {
+ return {
+ url:'https://pad.odoo.pad/p/test/' + args.context.object_id
+ };
+ },
+ pad_get_content: function () {
+ return "we should rewrite this server in haskell";
+ },
+ },
+ };
+ },
+});
+
+ QUnit.test('pad widget display help if server not configured', function (assert) {
+ assert.expect(4);
+
+ var form = createView({
+ View: FormView,
+ model: 'task',
+ data: this.data,
+ arch:'<form>' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="description" widget="pad"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ mockRPC: function (route, args) {
+ if (args.method === 'pad_is_configured') {
+ return $.when(false);
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+ assert.ok(form.$('p.oe_unconfigured').is(':visible'),
+ "help message should be visible");
+ assert.notOk(form.$('p.oe_pad_content').is(':visible'),
+ "content should not be visible");
+ form.$buttons.find('.o_form_button_edit').click();
+ assert.ok(form.$('p.oe_unconfigured').is(':visible'),
+ "help message should be visible");
+ assert.notOk(form.$('p.oe_pad_content').is(':visible'),
+ "content should not be visible");
+ form.destroy();
+ delete FieldPad.prototype.isPadConfigured;
+ });
+
+ QUnit.test('pad widget works, basic case', function (assert) {
+ assert.expect(5);
+
+ var form = createView({
+ View: FormView,
+ model: 'task',
+ data: this.data,
+ arch:'<form>' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="description" widget="pad"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ mockRPC: function (route, args) {
+ if (route === 'https://pad.odoo.pad/p/test/1?showChat=false&userName=batman') {
+ assert.ok(true, "should have an iframe with correct src");
+ return $.when(true);
+ }
+ return this._super.apply(this, arguments);
+ },
+ session: {
+ userName: "batman",
+ },
+ });
+ assert.notOk(form.$('p.oe_unconfigured').is(':visible'),
+ "help message should not be visible");
+ assert.ok(form.$('.oe_pad_content').is(':visible'),
+ "content should be visible");
+ assert.strictEqual(form.$('.oe_pad_content:contains(This pad will be)').length, 1,
+ "content should display a message when not initialized");
+
+ form.$buttons.find('.o_form_button_edit').click();
+
+ assert.strictEqual(form.$('.oe_pad_content iframe').length, 1,
+ "should have an iframe");
+
+ form.destroy();
+ delete FieldPad.prototype.isPadConfigured;
+ });
+
+ QUnit.test('pad widget works, with existing data', function (assert) {
+ assert.expect(2);
+
+ var contentDef = $.Deferred();
+
+ var form = createView({
+ View: FormView,
+ model: 'task',
+ data: this.data,
+ arch:'<form>' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="description" widget="pad"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 2,
+ mockRPC: function (route, args) {
+ var result = this._super.apply(this, arguments);
+ if (args.method === 'pad_get_content') {
+ return contentDef.then(_.constant(result));
+ }
+ return result;
+ },
+ session: {
+ userName: "batman",
+ },
+ });
+ assert.strictEqual(form.$('.oe_pad_content').text(), "Loading",
+ "should display loading message");
+ contentDef.resolve();
+ assert.strictEqual(form.$('.oe_pad_content').text(), "we should rewrite this server in haskell",
+ "should display proper value");
+ form.destroy();
+ delete FieldPad.prototype.isPadConfigured;
+ });
+
+});
diff --git a/addons/pad/views/pad.xml b/addons/pad/views/pad.xml
index 56bc0b1a997..126f8c84f16 100644
--- a/addons/pad/views/pad.xml
+++ b/addons/pad/views/pad.xml
@@ -6,4 +6,10 @@
<script type="text/javascript" src="/pad/static/src/js/pad.js" />
</xpath>
</template>
+
+ <template id="qunit_suite" name="pad tests" inherit_id="web.qunit_suite">
+ <xpath expr="//script[last()]" position="after">
+ <script type="text/javascript" src="/pad/static/tests/pad_tests.js"></script>
+ </xpath>
+ </template>
</odoo>
diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py
index 535a56c2336..385f425e955 100644
--- a/addons/payment/models/payment_acquirer.py
+++ b/addons/payment/models/payment_acquirer.py
@@ -507,7 +507,7 @@ class PaymentTransaction(models.Model):
tx.write({'reference': str(tx.id)})
# Generate callback hash if it is configured on the tx; avoid generating unnecessary stuff
- if tx.callback_model_id and tx.callback_res_id and tx.callback_method:
+ if tx.callback_model_id and tx.callback_res_id and tx.sudo().callback_method:
tx.write({'callback_hash': tx._generate_callback_hash()})
return tx
@@ -547,7 +547,9 @@ class PaymentTransaction(models.Model):
def _generate_callback_hash(self):
self.ensure_one()
secret = self.env['ir.config_parameter'].sudo().get_param('database.secret')
- token = '%s%s%s' % (self.callback_model_id.model, self.callback_res_id, self.callback_method)
+ token = '%s%s%s' % (self.callback_model_id.model,
+ self.callback_res_id,
+ self.sudo().callback_method)
return hmac.new(str(secret), token, hashlib.sha256).hexdigest()
# --------------------------------------------------
@@ -635,7 +637,7 @@ class PaymentTransaction(models.Model):
@api.multi
def execute_callback(self):
res = None
- for transaction in self.filtered(lambda tx: tx.callback_model_id and tx.callback_res_id and tx.callback_method):
+ for transaction in self.filtered(lambda tx: tx.callback_model_id and tx.callback_res_id and tx.sudo().callback_method):
valid_token = transaction._generate_callback_hash()
if not consteq(ustr(valid_token), transaction.callback_hash):
_logger.warning("Invalid callback signature for transaction %d" % (transaction.id))
@@ -643,7 +645,7 @@ class PaymentTransaction(models.Model):
record = self.env[transaction.callback_model_id.model].browse(transaction.callback_res_id).exists()
if record:
- res = getattr(record, transaction.callback_method)(transaction)
+ res = getattr(record, transaction.sudo().callback_method)(transaction)
else:
_logger.warning("Did not found record %s.%s for callback of transaction %d" % (transaction.callback_model_id.model, transaction.callback_res_id, transaction.id))
return res
diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py
index ebcddbfcfdf..a485a704978 100644
--- a/addons/point_of_sale/models/pos_order.py
+++ b/addons/point_of_sale/models/pos_order.py
@@ -677,7 +677,7 @@ class PosOrder(models.Model):
qty = 0
qty_done = 0
pack_lots = []
- pos_pack_lots = PosPackOperationLot.search([('order_id', '=', order.id), ('product_id', '=', pack_operation.product_id.id)])
+ pos_pack_lots = PosPackOperationLot.search([('order_id', '=', order.id), ('product_id', '=', pack_operation.product_id.id)])
pack_lot_names = [pos_pack.lot_name for pos_pack in pos_pack_lots]
if pack_lot_names and lots_necessary:
diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml
index 04c59ac13fb..71e4ca2c1c8 100644
--- a/addons/point_of_sale/static/src/xml/pos.xml
+++ b/addons/point_of_sale/static/src/xml/pos.xml
@@ -753,7 +753,7 @@
<t t-if='simple'>
<line>
<left><t t-esc='line.product_name_wrapped[0]' /></left>
- <right><value><t t-esc='line.price_display' /></value></right>
+ <right><value t-att-value-decimals='pos.currency.decimals'>><t t-esc='line.price_display' /></value></right>
</line>
<t t-call="XmlReceiptWrappedProductNameLines"/>
</t>
@@ -765,19 +765,19 @@
</t>
<line indent='1'>
<left>
- <value value-decimals='3' value-autoint='on'>
+ <value t-att-value-decimals='pos.dp["Product Unit of Measure"]' value-autoint='on'>
<t t-esc='line.quantity' />
</value>
<t t-if='line.unit_name !== "Unit(s)"'>
<t t-esc='line.unit_name' />
</t>
x
- <value value-decimals='2'>
+ <value t-att-value-decimals='pos.dp["Product Price"]'>
<t t-esc='line.price' />
</value>
</left>
<right>
- <value><t t-esc='line.price_display' /></value>
+ <value t-att-value-decimals='pos.currency.decimals'><t t-esc='line.price_display' /></value>
</right>
</line>
</t>
@@ -789,11 +789,11 @@
<t t-set='taxincluded' t-value='Math.abs(receipt.subtotal - receipt.total_with_tax) &lt;= 0.000001' />
<t t-if='!taxincluded'>
<line><right>--------</right></line>
- <line><left>Subtotal</left><right> <value><t t-esc="receipt.subtotal" /></value></right></line>
+ <line><left>Subtotal</left><right><value t-att-value-decimals='pos.currency.decimals'><t t-esc="receipt.subtotal" /></value></right></line>
<t t-foreach='receipt.tax_details' t-as='tax'>
<line>
<left><t t-esc='tax.name' /></left>
- <right><value><t t-esc='tax.amount' /></value></right>
+ <right><value t-att-value-decimals='pos.currency.decimals'><t t-esc='tax.amount' /></value></right>
</line>
</t>
</t>
@@ -803,7 +803,7 @@
<line><right>--------</right></line>
<line class='total' size='double-height'>
<left><pre> TOTAL</pre></left>
- <right><value><t t-esc='receipt.total_with_tax' /></value></right>
+ <right><value t-att-value-decimals='pos.currency.decimals'><t t-esc='receipt.total_with_tax' /></value></right>
</line>
<br/><br/>
@@ -812,14 +812,14 @@
<t t-foreach='paymentlines' t-as='line'>
<line>
<left><t t-esc='line.name' /></left>
- <right><value><t t-esc='line.get_amount()'/></value></right>
+ <right><value t-att-value-decimals='pos.currency.decimals'><t t-esc='line.get_amount()'/></value></right>
</line>
</t>
<br/>
<line size='double-height'>
<left><pre> CHANGE</pre></left>
- <right><value><t t-esc='receipt.change' /></value></right>
+ <right><value t-att-value-decimals='pos.currency.decimals'><t t-esc='receipt.change' /></value></right>
</line>
<br/>
@@ -828,19 +828,19 @@
<t t-if='receipt.total_discount'>
<line>
<left>Discounts</left>
- <right><value><t t-esc='receipt.total_discount'/></value></right>
+ <right><value t-att-value-decimals='pos.currency.decimals'><t t-esc='receipt.total_discount'/></value></right>
</line>
</t>
<t t-if='taxincluded'>
<t t-foreach='receipt.tax_details' t-as='tax'>
<line>
<left><t t-esc='tax.name' /></left>
- <right><value><t t-esc='tax.amount' /></value></right>
+ <right><value t-att-value-decimals='pos.currency.decimals'><t t-esc='tax.amount' /></value></right>
</line>
</t>
<line>
<left>Total Taxes</left>
- <right><value><t t-esc='receipt.total_tax'/></value></right>
+ <right><value t-att-value-decimals='pos.currency.decimals'><t t-esc='receipt.total_tax'/></value></right>
</line>
</t>
diff --git a/addons/pos_mercury/models/pos_mercury_transaction.py b/addons/pos_mercury/models/pos_mercury_transaction.py
index bd190e82f0d..7c2567af8df 100644
--- a/addons/pos_mercury/models/pos_mercury_transaction.py
+++ b/addons/pos_mercury/models/pos_mercury_transaction.py
@@ -15,7 +15,7 @@ class MercuryTransaction(models.Model):
_name = 'pos_mercury.mercury_transaction'
def _get_pos_session(self):
- pos_session = self.env['pos.session'].search([('state', '=', 'opened'), ('user_id', '=', self.env.uid)])
+ pos_session = self.env['pos.session'].search([('state', '=', 'opened'), ('user_id', '=', self.env.uid)], limit=1)
if not pos_session:
raise UserError("No POS session")
@@ -32,6 +32,7 @@ class MercuryTransaction(models.Model):
raise UserError("No Mercury configuration associated with the journal.")
def _setup_request(self, data):
+ # todo: in master make the client include the pos.session id and use that
pos_session = self._get_pos_session()
config = pos_session.config_id
diff --git a/addons/pos_restaurant/static/src/js/floors.js b/addons/pos_restaurant/static/src/js/floors.js
index e22cb8e3bde..bddc559804a 100644
--- a/addons/pos_restaurant/static/src/js/floors.js
+++ b/addons/pos_restaurant/static/src/js/floors.js
@@ -987,4 +987,11 @@ screens.define_action_button({
},
});
+return {
+ TableGuestsButton: TableGuestsButton,
+ TransferOrderButton:TransferOrderButton,
+ TableWidget: TableWidget,
+ FloorScreenWidget: FloorScreenWidget,
+};
+
});
diff --git a/addons/product/models/res_company.py b/addons/product/models/res_company.py
index 3d8d0dcfc70..d94e8d2cda2 100644
--- a/addons/product/models/res_company.py
+++ b/addons/product/models/res_company.py
@@ -18,12 +18,13 @@ class ResCompany(models.Model):
'currency_id': new_company.currency_id.id,
})
field = self.env['ir.model.fields']._get('res.partner', 'property_product_pricelist')
- self.env['ir.property'].create({
+ product_property = self.env['ir.property'].create({
'name': 'property_product_pricelist',
- 'company_id': new_company.id,
'value_reference': 'product.pricelist,%s' % pricelist.id,
'fields_id': field.id
})
+ # multi-company security rules prevents access
+ product_property.sudo().write({'company_id': new_company.id})
return new_company
@api.multi
diff --git a/addons/project_timesheet_holidays/models/hr_holidays.py b/addons/project_timesheet_holidays/models/hr_holidays.py
index c69cda4f2ff..2717a4eab59 100644
--- a/addons/project_timesheet_holidays/models/hr_holidays.py
+++ b/addons/project_timesheet_holidays/models/hr_holidays.py
@@ -52,6 +52,7 @@ class Holidays(models.Model):
'user_id': holiday.employee_id.user_id.id,
'date': fields.Date.to_string(day_date),
'holiday_id': holiday.id,
+ 'employee_id': holiday.employee_id.id,
})
return super(Holidays, self)._validate_leave_request()
diff --git a/addons/project_timesheet_holidays/tests/__init__.py b/addons/project_timesheet_holidays/tests/__init__.py
new file mode 100644
index 00000000000..a506a2840df
--- /dev/null
+++ b/addons/project_timesheet_holidays/tests/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import test_timesheet_holidays
diff --git a/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py b/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py
new file mode 100644
index 00000000000..f49cf00ed14
--- /dev/null
+++ b/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+
+from odoo import fields
+
+from odoo.addons.hr_timesheet.tests.test_timesheet import TestTimesheet
+
+
+class TestTimesheetHolidays(TestTimesheet):
+
+ def setUp(self):
+ super(TestTimesheetHolidays, self).setUp()
+
+ self.employee_working_calendar = self.empl_employee.resource_calendar_id
+ # leave dates : from next monday to next wednesday (to avoid crashing tests on weekend, when
+ # there is no work days in working calendar)
+ self.leave_start_datetime = datetime.today().replace(hour=7, minute=0) + relativedelta(weeks=0, days=1, weekday=0)
+ self.leave_end_datetime = self.leave_start_datetime + relativedelta(days=3)
+
+ # all company have those internal project/task (created by default)
+ self.internal_project = self.env.user.company_id.leave_timesheet_project_id
+ self.internal_task_leaves = self.env.user.company_id.leave_timesheet_task_id
+
+ self.leave_type_with_ts = self.env['hr.holidays.status'].create({
+ 'name': 'Leave Type with timesheet generation',
+ 'limit': True,
+ 'timesheet_generate': True,
+ 'timesheet_project_id': self.internal_project.id,
+ 'timesheet_task_id': self.internal_task_leaves.id,
+ })
+ self.leave_type_no_ts = self.env['hr.holidays.status'].create({
+ 'name': 'Leave Type without timesheet generation',
+ 'limit': True,
+ 'timesheet_generate': False,
+ 'timesheet_project_id': False,
+ 'timesheet_task_id': False,
+ })
+
+ # HR Officer allocates some leaves to the employee 1
+ self.Holidays = self.env['hr.holidays'].with_context(mail_create_nolog=True, mail_notrack=True)
+ self.leave_allocation_with_ts = self.Holidays.sudo().create({
+ 'name': 'Days for limited category with timesheet',
+ 'employee_id': self.empl_employee.id,
+ 'holiday_status_id': self.leave_type_with_ts.id,
+ 'type': 'add',
+ 'number_of_days_temp': 10,
+ })
+ self.leave_allocation_with_ts.action_approve()
+ self.leave_allocation_no_ts = self.Holidays.sudo().create({
+ 'name': 'Days for limited category without timesheet',
+ 'employee_id': self.empl_employee.id,
+ 'holiday_status_id': self.leave_type_no_ts.id,
+ 'type': 'add',
+ 'number_of_days_temp': 10,
+ })
+ self.leave_allocation_no_ts.action_approve()
+
+ def test_validate_with_timesheet(self):
+ # employee creates a leave request
+ number_of_days = (self.leave_end_datetime - self.leave_start_datetime).days+1
+ holiday = self.Holidays.sudo(self.user_employee.id).create({
+ 'name': 'Leave 1',
+ 'employee_id': self.empl_employee.id,
+ 'holiday_status_id': self.leave_type_with_ts.id,
+ 'date_from': self.leave_start_datetime,
+ 'date_to': self.leave_end_datetime,
+ 'number_of_days_temp': number_of_days,
+ })
+ holiday.sudo().action_validate()
+ self.assertEquals(len(holiday.timesheet_ids), number_of_days, 'Number of generated timesheets should be the same as the leave duration (1 per day)')
+
+ def test_validate_without_timesheet(self):
+ # employee creates a leave request
+ number_of_days = (self.leave_end_datetime - self.leave_start_datetime).days
+ holiday = self.Holidays.sudo(self.user_employee.id).create({
+ 'name': 'Leave 1',
+ 'employee_id': self.empl_employee.id,
+ 'holiday_status_id': self.leave_type_no_ts.id,
+ 'date_from': self.leave_start_datetime,
+ 'date_to': self.leave_end_datetime,
+ 'number_of_days_temp': number_of_days,
+ })
+ holiday.sudo().action_validate()
+ self.assertEquals(len(holiday.timesheet_ids), 0, 'Number of generated timesheets should be zero since the leave type does not generate timesheet')
diff --git a/addons/sale/report/sale_report.xml b/addons/sale/report/sale_report.xml
index 76012187110..ace51bb0861 100644
--- a/addons/sale/report/sale_report.xml
+++ b/addons/sale/report/sale_report.xml
@@ -10,15 +10,5 @@
name="sale.report_saleorder"
print_report_name="(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or 'Order - %s' % (object.name)"
/>
-
- <report
- string="Pro-Forma"
- id="report_proforma_quotation"
- model="sale.order"
- report_type="qweb-pdf"
- name="sale.report_saleproforma"
- file="sale.report_saleorder"
- print_report_name="'Pro-Forma - %s' % (object.name)"
- />
</data>
</odoo>
diff --git a/addons/sale/report/sale_report_templates.xml b/addons/sale/report/sale_report_templates.xml
index 3373c74750f..4a41add611c 100644
--- a/addons/sale/report/sale_report_templates.xml
+++ b/addons/sale/report/sale_report_templates.xml
@@ -29,11 +29,11 @@
</div>
<h2>
- <t t-if="not proforma">
+ <t t-if="not env.context.get('proforma', False)">
<span t-if="doc.state not in ['draft','sent']">Order # </span>
<span t-if="doc.state in ['draft','sent']">Quotation # </span>
</t>
- <t t-if="proforma">
+ <t t-if="env.context.get('proforma', False)">
<span>Pro-Forma # </span>
</t>
<span t-field="doc.name"/>
diff --git a/addons/sale/security/sale_security.xml b/addons/sale/security/sale_security.xml
index 32c1d36917e..0a269ab44bf 100644
--- a/addons/sale/security/sale_security.xml
+++ b/addons/sale/security/sale_security.xml
@@ -4,7 +4,6 @@
<record id="sale.group_sale_layout" model="res.groups">
<field name="name">Personalize sales order and invoice report</field>
<field name="category_id" ref="base.module_category_hidden"/>
- <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="group_delivery_invoice_address" model="res.groups">
diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py
index 3e28cbb9575..886d80d19bd 100644
--- a/addons/sale/wizard/sale_make_invoice_advance.py
+++ b/addons/sale/wizard/sale_make_invoice_advance.py
@@ -82,10 +82,11 @@ class SaleAdvancePaymentInv(models.TransientModel):
else:
amount = self.amount
name = _('Down Payment')
- if order.fiscal_position_id and self.product_id.taxes_id:
- tax_ids = order.fiscal_position_id.map_tax(self.product_id.taxes_id).ids
+ taxes = self.product_id.taxes_id.filtered(lambda r: not order.company_id or r.company_id == order.company_id)
+ if order.fiscal_position_id and taxes:
+ tax_ids = order.fiscal_position_id.map_tax(taxes).ids
else:
- tax_ids = self.product_id.taxes_id.ids
+ tax_ids = taxes.ids
invoice = inv_obj.create({
'name': order.client_order_ref or order.name,
@@ -145,10 +146,11 @@ class SaleAdvancePaymentInv(models.TransientModel):
raise UserError(_('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.'))
if self.product_id.type != 'service':
raise UserError(_("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product."))
- if order.fiscal_position_id and self.product_id.taxes_id:
- tax_ids = order.fiscal_position_id.map_tax(self.product_id.taxes_id).ids
+ taxes = self.product_id.taxes_id.filtered(lambda r: not order.company_id or r.company_id == order.company_id)
+ if order.fiscal_position_id and taxes:
+ tax_ids = order.fiscal_position_id.map_tax(taxes).ids
else:
- tax_ids = self.product_id.taxes_id.ids
+ tax_ids = taxes.ids
so_line = sale_line_obj.create({
'name': _('Advance: %s') % (time.strftime('%m %Y'),),
'price_unit': amount,
diff --git a/addons/sale_mrp/sale_mrp.py b/addons/sale_mrp/sale_mrp.py
index 846c6e656f6..3eff4493250 100644
--- a/addons/sale_mrp/sale_mrp.py
+++ b/addons/sale_mrp/sale_mrp.py
@@ -42,6 +42,30 @@ class SaleOrderLine(models.Model):
return 0.0
return super(SaleOrderLine, self)._get_delivered_qty()
+ @api.multi
+ def _get_bom_component_qty(self, bom):
+ bom_quantity = self.product_uom._compute_quantity(self.product_uom_qty, bom.product_uom_id)
+ boms, lines = bom.explode(self.product_id, bom_quantity)
+ components = {}
+ for line, line_data in lines:
+ product = line.product_id.id
+ uom = line.product_uom_id
+ qty = line.product_qty
+ if components.get(product, False):
+ if uom.id != components[product]['uom']:
+ from_uom = uom
+ to_uom = self.env['product.uom'].browse(components[product]['uom'])
+ qty = from_uom._compute_quantity(qty, to_uom_id=to_uom)
+ components[product]['qty'] += qty
+ else:
+ # To be in the uom reference of the product
+ to_uom = self.env['product.product'].browse(product).uom_id
+ if uom.id != to_uom.id:
+ from_uom = uom
+ qty = from_uom._compute_quantity(qty, to_uom_id=to_uom)
+ components[product] = {'qty': qty, 'uom': to_uom.id}
+ return components
+
class AccountInvoiceLine(models.Model):
# TDE FIXME: what is this code ??
diff --git a/addons/sale_timesheet/models/account.py b/addons/sale_timesheet/models/account.py
index f544091a1f9..155246b1c0c 100644
--- a/addons/sale_timesheet/models/account.py
+++ b/addons/sale_timesheet/models/account.py
@@ -55,7 +55,7 @@ class AccountAnalyticLine(models.Model):
unit_amount = values.get('unit_amount', 0.0) or self.unit_amount
# find the employee
- employee_id = values.get('employee_id') or self.employee_id.id or self._default_employee_id().id
+ employee_id = values.get('employee_id') or self.employee_id.id or (self.env.user.employee_ids and self.env.user.employee_ids[0].id or False)
employee = self.env['hr.employee'].browse(employee_id) if employee_id else self.env['hr.employee']
if not employee:
user_id = values.get('user_id') or self.user_id.id or self._default_user()
@@ -63,6 +63,9 @@ class AccountAnalyticLine(models.Model):
# find the analytic account
account_id = values.get('account_id') or self.account_id.id
+ if not account_id and values.get('project_id'):
+ project = self.env['project.project'].browse(values['project_id'])
+ account_id = project.analytic_account_id.id
analytic_account = self.env['account.analytic.account'].browse(account_id) if account_id else self.env['account.analytic.account']
# convert employee cost into timesheet (analytic account) currency
@@ -107,13 +110,13 @@ class AccountAnalyticLine(models.Model):
analytic_account = self.env['account.analytic.account'].browse(account_id)
# calculate the revenue on the timesheet
if so_line.product_id.invoice_policy == 'delivery':
- delivered_revenue = unit_amount * so_line.price_unit * (1-so_line.discount)
- revenue = so_line.currency_id.compute(delivered_revenue, analytic_account.currency_id) # amount from SO should be convert into analytic account currency
+ sale_price_unit = so_line.currency_id.compute(so_line.price_unit, analytic_account.currency_id) # amount from SO should be convert into analytic account currency
+ revenue = analytic_account.currency_id.round(unit_amount * sale_price_unit * (1-so_line.discount))
billable_type = 'billable_time'
elif so_line.product_id.invoice_policy == 'order' and so_line.product_id.track_service == 'task':
# compute the total revenue the SO since we are in fixed price
- total_revenue_so = so_line.product_uom_qty * so_line.price_unit * (1-so_line.discount)
- total_revenue_so = so_line.currency_id.compute(total_revenue_so, analytic_account.currency_id)
+ sale_price_unit = so_line.currency_id.compute(so_line.price_unit, analytic_account.currency_id)
+ total_revenue_so = analytic_account.currency_id.round(so_line.product_uom_qty * sale_price_unit * (1-so_line.discount))
# compute the total revenue already existing (without the current timesheet line)
domain = [('so_line', '=', so_line.id)]
if self.ids:
@@ -122,7 +125,7 @@ class AccountAnalyticLine(models.Model):
total_revenue_invoiced = sum(analytic_lines.mapped('timesheet_revenue'))
# compute (new) revenue of current timesheet line
revenue = min(
- so_line.currency_id.compute(unit_amount * (so_line.price_unit) * (1-so_line.discount), analytic_account.currency_id),
+ analytic_account.currency_id.round(unit_amount * so_line.currency_id.compute(so_line.price_unit, analytic_account.currency_id) * (1-so_line.discount)),
total_revenue_so - total_revenue_invoiced
)
billable_type = 'billable_fixed'
diff --git a/addons/sale_timesheet/models/account_invoice.py b/addons/sale_timesheet/models/account_invoice.py
index 13de1c8c843..64ac5d7a8aa 100644
--- a/addons/sale_timesheet/models/account_invoice.py
+++ b/addons/sale_timesheet/models/account_invoice.py
@@ -71,14 +71,14 @@ class AccountInvoice(models.Model):
total_revenue_per_currency = dict.fromkeys(uninvoiced_timesheet_lines.mapped('company_currency_id').ids, 0.0)
for index, timesheet_line in enumerate(uninvoiced_timesheet_lines):
if index+1 != len(uninvoiced_timesheet_lines):
- line_revenue = invoiced_price_per_hour * timesheet_line.unit_amount
+ line_revenue = invoice_line.currency_id.compute(invoiced_price_per_hour, timesheet_line.company_currency_id) * timesheet_line.unit_amount
total_revenue_per_currency[timesheet_line.company_currency_id.id] += line_revenue
else: # last line: add the difference to avoid rounding problem
total_revenue = sum([self.env['res.currency'].browse(currency_id).compute(amount, timesheet_line.company_currency_id) for currency_id, amount in total_revenue_per_currency.items()])
- line_revenue = invoice_line.price_subtotal - total_revenue
+ line_revenue = invoice_line.currency_id.compute(invoice_line.price_subtotal, timesheet_line.company_currency_id) - total_revenue
timesheet_line.write({
'timesheet_invoice_id': invoice.id,
- 'timesheet_revenue': float_round(line_revenue, precision),
+ 'timesheet_revenue': timesheet_line.company_currency_id.round(line_revenue),
})
# ordered : update revenue with the prorata of theorical revenue
@@ -105,5 +105,5 @@ class AccountInvoice(models.Model):
timesheet_line.write({
'timesheet_invoice_id': invoice.id,
- 'timesheet_revenue': float_round(line_revenue, precision),
+ 'timesheet_revenue': timesheet_line.company_currency_id.round(line_revenue),
})
diff --git a/addons/sale_timesheet/models/procurement.py b/addons/sale_timesheet/models/procurement.py
index bd7e4c85329..437a6f7398c 100644
--- a/addons/sale_timesheet/models/procurement.py
+++ b/addons/sale_timesheet/models/procurement.py
@@ -71,7 +71,7 @@ class ProcurementOrder(models.Model):
'partner_id': self.sale_line_id.order_id.partner_id.id or self.partner_dest_id.id,
'user_id': self.env.uid,
'procurement_id': self.id,
- 'description': self.name + '\n',
+ 'description': self.name + '<br/>',
'project_id': project.id,
'company_id': self.company_id.id,
}
diff --git a/addons/sale_timesheet/tests/__init__.py b/addons/sale_timesheet/tests/__init__.py
index ae48badd8a2..502409b7144 100644
--- a/addons/sale_timesheet/tests/__init__.py
+++ b/addons/sale_timesheet/tests/__init__.py
@@ -1,2 +1,6 @@
-from . import test_sale_timesheet
-from . import test_sale_service
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+#from . import test_sale_timesheet
+#from . import test_sale_service
+from . import test_timesheet_revenue
diff --git a/addons/sale_timesheet/tests/test_timesheet_revenue.py b/addons/sale_timesheet/tests/test_timesheet_revenue.py
new file mode 100644
index 00000000000..7d62f088a94
--- /dev/null
+++ b/addons/sale_timesheet/tests/test_timesheet_revenue.py
@@ -0,0 +1,284 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo.addons.sale.tests.test_sale_common import TestSale
+
+
+class TestSaleTimesheet(TestSale):
+
+ def setUp(self):
+ super(TestSaleTimesheet, self).setUp()
+ # create project
+ self.project = self.env['project.project'].create({
+ 'name': 'Project for my timesheets',
+ 'allow_timesheets': True,
+ 'use_tasks': True,
+ })
+
+ # create service products
+ self.product_deliver = self.env['product.product'].create({
+ 'name': "Delivered Service",
+ 'standard_price': 30,
+ 'list_price': 90,
+ 'type': 'service',
+ 'invoice_policy': 'delivery',
+ 'uom_id': self.env.ref('product.product_uom_hour').id,
+ 'uom_po_id': self.env.ref('product.product_uom_hour').id,
+ 'default_code': 'SERV-DELI',
+ 'track_service': 'task',
+ 'project_id': self.project.id
+ })
+
+ self.product_order = self.env['product.product'].create({
+ 'name': "Ordered Service",
+ 'standard_price': 37,
+ 'list_price': 51,
+ 'type': 'service',
+ 'invoice_policy': 'order',
+ 'uom_id': self.env.ref('product.product_uom_hour').id,
+ 'uom_po_id': self.env.ref('product.product_uom_hour').id,
+ 'default_code': 'SERV-ORDER',
+ 'track_service': 'task',
+ 'project_id': self.project.id
+ })
+
+ # pricelists
+ self.pricelist_usd = self.env['product.pricelist'].create({
+ 'name': 'USD pricelist',
+ 'active': True,
+ 'currency_id': self.env.ref('base.USD').id,
+ 'company_id': self.env.user.company_id.id,
+ })
+ self.pricelist_eur = self.env['product.pricelist'].create({
+ 'name': 'EUR pricelist',
+ 'active': True,
+ 'currency_id': self.env.ref('base.EUR').id,
+ 'company_id': self.env.user.company_id.id,
+ })
+
+ # partners
+ self.partner_usd = self.env['res.partner'].create({
+ 'name': 'Cool Partner in USD',
+ 'email': 'partner.usd@test.com',
+ 'property_product_pricelist': self.pricelist_usd.id,
+ })
+ self.partner_eur = self.env['res.partner'].create({
+ 'name': 'Cool partner in EUR',
+ 'email': 'partner.eur@test.com',
+ 'property_product_pricelist': self.pricelist_eur.id,
+ })
+
+ def test_revenue(self):
+ """ Create a SO with 2 lines : one for a delivered service, one for a ordered service. Confirm
+ and invoice it. For this, we use a partner having the same currency as the current company.
+ 3 timesheets are logged before invoicing : 2 for delivered, 1 for ordered.
+ """
+ # create SO and confirm it
+ sale_order = self.env['sale.order'].create({
+ 'partner_id': self.partner_usd.id,
+ 'partner_invoice_id': self.partner_usd.id,
+ 'partner_shipping_id': self.partner_usd.id,
+ 'pricelist_id': self.pricelist_usd.id,
+ })
+ sale_order_line_delivered = self.env['sale.order.line'].create({
+ 'name': self.product_deliver.name,
+ 'product_id': self.product_deliver.id,
+ 'product_uom_qty': 12,
+ 'product_uom': self.product_deliver.uom_id.id,
+ 'price_unit': self.product_deliver.list_price,
+ 'order_id': sale_order.id,
+ })
+ sale_order_line_ordered = self.env['sale.order.line'].create({
+ 'name': self.product_order.name,
+ 'product_id': self.product_order.id,
+ 'product_uom_qty': 7,
+ 'product_uom': self.product_order.uom_id.id,
+ 'price_unit': self.product_order.list_price,
+ 'order_id': sale_order.id,
+ })
+ sale_order_line_ordered.product_id_change()
+ sale_order_line_delivered.product_id_change()
+ sale_order.action_confirm()
+
+ # log timesheet on tasks
+ task_delivered = self.env['project.task'].search([('sale_line_id', '=', sale_order_line_delivered.id)])
+ task_ordered = self.env['project.task'].search([('sale_line_id', '=', sale_order_line_ordered.id)])
+
+ timesheet1 = self.env['account.analytic.line'].create({
+ 'name': 'ts 1',
+ 'unit_amount': 5,
+ 'task_id': task_delivered.id,
+ 'project_id': task_delivered.project_id.id,
+ })
+ timesheet2 = self.env['account.analytic.line'].create({
+ 'name': 'ts 2',
+ 'unit_amount': 2,
+ 'task_id': task_delivered.id,
+ 'project_id': task_delivered.project_id.id,
+ })
+ timesheet3 = self.env['account.analytic.line'].create({
+ 'name': 'ts 3',
+ 'unit_amount': 3,
+ 'task_id': task_ordered.id,
+ 'project_id': task_ordered.project_id.id,
+ })
+
+ # check theorical revenue
+ self.assertEquals(timesheet1.timesheet_invoice_type, 'billable_time', "Billable type on task from delivered service should be 'billabe time'")
+ self.assertEquals(timesheet2.timesheet_invoice_type, 'billable_time', "Billable type on task from delivered service should be 'billabe time'")
+ self.assertEquals(timesheet3.timesheet_invoice_type, 'billable_fixed', "Billable type on task from ordered service should be 'billabe fixed'")
+ self.assertEquals(timesheet1.timesheet_invoice_id, self.env['account.invoice'])
+ self.assertEquals(timesheet2.timesheet_invoice_id, self.env['account.invoice'])
+ self.assertEquals(timesheet3.timesheet_invoice_id, self.env['account.invoice'])
+ # Hours * SO Line price_unit * (1-discount)
+ self.assertEquals(timesheet1.timesheet_revenue, 450, "Revenue computation does not return the correct amount !")
+ self.assertEquals(timesheet2.timesheet_revenue, 180, "Revenue computation does not return the correct amount !")
+ # MIN (
+ # 2 * 90 * (1 - 0.0) = 180
+ # (12 * 90) - 450 = 1080
+ # )
+ self.assertEquals(timesheet3.timesheet_revenue, 153, "Revenue computation does not return the correct amount !")
+
+ # invoice the SO
+ context = {
+ "active_model": 'sale.order',
+ "active_ids": [sale_order.id],
+ "active_id": sale_order.id,
+ 'open_invoices': True,
+ }
+ payment = self.env['sale.advance.payment.inv'].create({
+ 'advance_payment_method': 'delivered',
+ })
+ action_invoice = payment.with_context(context).create_invoices()
+ invoice_id = action_invoice['res_id']
+ invoice = self.env['account.invoice'].browse(invoice_id)
+
+ # check revenues have not changed
+ self.assertEquals(timesheet1.timesheet_revenue, 450, "Revenue computation does not return the correct amount !")
+ self.assertEquals(timesheet2.timesheet_revenue, 180, "Revenue computation does not return the correct amount !")
+ self.assertEquals(timesheet3.timesheet_revenue, 153, "Revenue computation does not return the correct amount !")
+
+ # update invoice line by setting a reduction, then validate it
+ for invoice_line in invoice.invoice_line_ids:
+ invoice_line.write({'price_unit': invoice_line.price_unit - 10})
+ invoice.action_invoice_open()
+
+ # check concrete revenue
+ # (Total inv line / SUM(uninvoiced timesheet for delivered service) ) * timesheet line hours, so
+ # (560 / 7 )* 5 = 400
+ # (560 / 7) * 2 = 160
+ self.assertEquals(timesheet1.timesheet_revenue, 400, "Revenue computation on invoice validation does not return the correct revenue !")
+ self.assertEquals(timesheet2.timesheet_revenue, 160, "Revenue computation on invoice validation does not return the correct revenue !")
+ # Since their is only one line, the total invoice line is set as revenue for ordered service
+ self.assertEquals(timesheet3.timesheet_revenue, 287, "Revenue computation on invoice validation does not return the correct revenue !")
+
+ # check the invoice is well set
+ self.assertEquals(timesheet1.timesheet_invoice_id, invoice)
+ self.assertEquals(timesheet2.timesheet_invoice_id, invoice)
+ self.assertEquals(timesheet3.timesheet_invoice_id, invoice)
+
+ def test_revenue_multi_currency(self):
+ """ Create a SO with 2 lines : one for a delivered service, one for a ordered service. Confirm
+ and invoice it. For this, we use a partner having a DIFFERENT currency from the current company.
+ 4 timesheets are logged before invoicing : 2 for delivered, 2 for ordered.
+ """
+ # create SO and confirm it
+ sale_order = self.env['sale.order'].create({
+ 'partner_id': self.partner_usd.id,
+ 'partner_invoice_id': self.partner_eur.id,
+ 'partner_shipping_id': self.partner_eur.id,
+ 'pricelist_id': self.pricelist_eur.id,
+ })
+ sale_order_line_delivered = self.env['sale.order.line'].create({
+ 'name': self.product_deliver.name,
+ 'product_id': self.product_deliver.id,
+ 'product_uom_qty': 12,
+ 'product_uom': self.product_deliver.uom_id.id,
+ 'price_unit': self.product_deliver.list_price,
+ 'order_id': sale_order.id,
+ })
+ sale_order_line_ordered = self.env['sale.order.line'].create({
+ 'name': self.product_order.name,
+ 'product_id': self.product_order.id,
+ 'product_uom_qty': 7,
+ 'product_uom': self.product_order.uom_id.id,
+ 'price_unit': self.product_order.list_price,
+ 'order_id': sale_order.id,
+ })
+ sale_order_line_ordered.product_id_change()
+ sale_order_line_delivered.product_id_change()
+ sale_order.action_confirm()
+
+ # log timesheet on tasks
+ task_delivered = self.env['project.task'].search([('sale_line_id', '=', sale_order_line_delivered.id)])
+ task_ordered = self.env['project.task'].search([('sale_line_id', '=', sale_order_line_ordered.id)])
+
+ timesheet1 = self.env['account.analytic.line'].create({
+ 'name': 'ts 1',
+ 'unit_amount': 5,
+ 'task_id': task_delivered.id,
+ 'project_id': task_delivered.project_id.id,
+ })
+ timesheet2 = self.env['account.analytic.line'].create({
+ 'name': 'ts 2',
+ 'unit_amount': 2,
+ 'task_id': task_delivered.id,
+ 'project_id': task_delivered.project_id.id,
+ })
+ timesheet3 = self.env['account.analytic.line'].create({
+ 'name': 'ts 3',
+ 'unit_amount': 3,
+ 'task_id': task_ordered.id,
+ 'project_id': task_ordered.project_id.id,
+ })
+ timesheet4 = self.env['account.analytic.line'].create({
+ 'name': 'ts 4',
+ 'unit_amount': 6,
+ 'task_id': task_ordered.id,
+ 'project_id': task_ordered.project_id.id,
+ })
+
+ # check theorical revenue
+ # Note: conversion from EUR to USD is *1.2833309567944147
+ self.assertEquals(timesheet1.timesheet_invoice_type, 'billable_time', "Billable type on task from delivered service should be 'billabe time'")
+ self.assertEquals(timesheet2.timesheet_invoice_type, 'billable_time', "Billable type on task from delivered service should be 'billabe time'")
+ self.assertEquals(timesheet3.timesheet_invoice_type, 'billable_fixed', "Billable type on task from ordered service should be 'billabe fixed'")
+ self.assertEquals(timesheet4.timesheet_invoice_type, 'billable_fixed', "Billable type on task from ordered service should be 'billabe fixed'")
+ self.assertEquals(timesheet1.timesheet_invoice_id, self.env['account.invoice'])
+ self.assertEquals(timesheet2.timesheet_invoice_id, self.env['account.invoice'])
+ self.assertEquals(timesheet3.timesheet_invoice_id, self.env['account.invoice'])
+ # Same computation as the test below, since revenue is stored in company currency
+ self.assertEquals(timesheet1.timesheet_revenue, 450, "Revenue computation does not return the correct amount !")
+ self.assertEquals(timesheet2.timesheet_revenue, 180, "Revenue computation does not return the correct amount !")
+ self.assertEquals(timesheet3.timesheet_revenue, 153, "Revenue computation does not return the correct amount !")
+ self.assertEquals(timesheet4.timesheet_revenue, 204, "Revenue computation does not return the correct amount !")
+
+ # invoice the SO
+ context = {
+ "active_model": 'sale.order',
+ "active_ids": [sale_order.id],
+ "active_id": sale_order.id,
+ 'open_invoices': True,
+ }
+ payment = self.env['sale.advance.payment.inv'].create({
+ 'advance_payment_method': 'delivered',
+ })
+ action_invoice = payment.with_context(context).create_invoices()
+ invoice_id = action_invoice['res_id']
+ invoice = self.env['account.invoice'].browse(invoice_id)
+
+ # update invoice line by setting a reduction, then validate it
+ for invoice_line in invoice.invoice_line_ids:
+ invoice_line.write({'price_unit': invoice_line.price_unit - 10})
+ invoice.action_invoice_open()
+
+ # check concrete revenue
+ self.assertEquals(timesheet1.timesheet_revenue, 385.85, "Revenue computation on invoice validation does not return the correct revenue !")
+ self.assertEquals(timesheet2.timesheet_revenue, 154.35, "Revenue computation on invoice validation does not return the correct revenue !")
+ self.assertEquals(timesheet3.timesheet_revenue, 114.5, "Revenue computation on invoice validation does not return the correct revenue !")
+ self.assertEquals(timesheet4.timesheet_revenue, 152.68, "Revenue computation on invoice validation does not return the correct revenue !")
+
+ # check the invoice is well set
+ self.assertEquals(timesheet1.timesheet_invoice_id, invoice)
+ self.assertEquals(timesheet2.timesheet_invoice_id, invoice)
+ self.assertEquals(timesheet3.timesheet_invoice_id, invoice)
diff --git a/addons/sales_team/static/src/js/sales_team_dashboard.js b/addons/sales_team/static/src/js/sales_team_dashboard.js
index ed961aa19b0..bd7f708cf37 100644
--- a/addons/sales_team/static/src/js/sales_team_dashboard.js
+++ b/addons/sales_team/static/src/js/sales_team_dashboard.js
@@ -132,19 +132,37 @@ var SalesTeamDashboardRenderer = KanbanRenderer.extend({
});
var SalesTeamDashboardModel = KanbanModel.extend({
+ /**
+ * @override
+ */
+ init: function () {
+ this.dashboardValues = {};
+ this._super.apply(this, arguments);
+ },
+
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
/**
- * @œverride
+ * @override
+ */
+ get: function (localID) {
+ var result = this._super.apply(this, arguments);
+ if (this.dashboardValues[localID]) {
+ result.dashboardValues = this.dashboardValues[localID];
+ }
+ return result;
+ },
+ /**
+ * @override
* @returns {Deferred}
*/
load: function () {
return this._loadDashboard(this._super.apply(this, arguments));
},
/**
- * @œverride
+ * @override
* @returns {Deferred}
*/
reload: function () {
@@ -157,6 +175,7 @@ var SalesTeamDashboardModel = KanbanModel.extend({
/**
* @abstract
+ * @private
* @returns {Deferred -> Object} resolves to the required dashboard data
*/
_fetchDashboardData: function () {
@@ -171,8 +190,7 @@ var SalesTeamDashboardModel = KanbanModel.extend({
var self = this;
var dashboard_def = this._fetchDashboardData();
return $.when(super_def, dashboard_def).then(function (id, dashboardValues) {
- var dataPoint = self.localData[id];
- dataPoint.dashboardValues = dashboardValues;
+ self.dashboardValues[id] = dashboardValues;
return id;
});
},
diff --git a/addons/stock/models/procurement.py b/addons/stock/models/procurement.py
index 8cf07b02c36..8012a1b2a19 100644
--- a/addons/stock/models/procurement.py
+++ b/addons/stock/models/procurement.py
@@ -274,6 +274,11 @@ class ProcurementOrder(models.Model):
def _procurement_from_orderpoint_post_process(self, orderpoint_ids):
return True
+ def _get_orderpoint_domain(self, company_id=False):
+ domain = [('company_id', '=', company_id)] if company_id else []
+ domain += [('product_id.active', '=', True)]
+ return domain
+
@api.model
def _procure_orderpoint_confirm(self, use_new_cursor=False, company_id=False):
""" Create procurements based on orderpoints.
@@ -283,9 +288,7 @@ class ProcurementOrder(models.Model):
"""
OrderPoint = self.env['stock.warehouse.orderpoint']
-
- domain = [('company_id', '=', company_id)] if company_id else []
- domain += [('product_id.active', '=', True)]
+ domain = self._get_orderpoint_domain(company_id=company_id)
orderpoints_noprefetch = OrderPoint.with_context(prefetch_fields=False).search(domain,
order=self._procurement_from_orderpoint_get_order()).ids
while orderpoints_noprefetch:
diff --git a/addons/stock/models/res_company.py b/addons/stock/models/res_company.py
index c1fd7aff521..6860ce7496b 100644
--- a/addons/stock/models/res_company.py
+++ b/addons/stock/models/res_company.py
@@ -23,14 +23,17 @@ class Company(models.Model):
location = self.env['stock.location'].create({
'name': _('%s: Transit Location') % self.name,
'usage': 'transit',
- 'company_id': self.id,
'location_id': parent_location and parent_location.id or False,
})
+ location.sudo().write({'company_id': self.id})
self.write({'internal_transit_location_id': location.id})
@api.model
def create(self, vals):
company = super(Company, self).create(vals)
- self.env['stock.warehouse'].create({'name': company.name, 'code': company.name[:5], 'company_id': company.id})
+
+ # multi-company rules prevents creating warehouse and sub-locations
+ self.env['stock.warehouse'].check_access_rights('create')
+ self.env['stock.warehouse'].sudo().create({'name': company.name, 'code': company.name[:5], 'company_id': company.id})
company.create_transit_location()
return company
diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py
index 7a806be4478..d6aafc6f19b 100644
--- a/addons/stock/models/stock_move.py
+++ b/addons/stock/models/stock_move.py
@@ -495,9 +495,12 @@ class StockMove(models.Model):
self._push_apply()
return self
+ def _set_default_price_moves(self):
+ return self.filtered(lambda move: not move.price_unit)
+
def set_default_price_unit_from_product(self):
""" Set price to move, important in inter-company moves or receipts with only one partner """
- for move in self.filtered(lambda move: not move.price_unit):
+ for move in self._set_default_price_moves():
move.write({'price_unit': move.product_id.standard_price})
attribute_price = set_default_price_unit_from_product
diff --git a/addons/stock/views/stock_picking_views.xml b/addons/stock/views/stock_picking_views.xml
index 5d5f2b2b4e6..ff42bf3095a 100644
--- a/addons/stock/views/stock_picking_views.xml
+++ b/addons/stock/views/stock_picking_views.xml
@@ -226,7 +226,7 @@
<h1 class="hidden-xs">
<field name="name" attrs="{'invisible': [('name','=','/')]}" readonly="1"/>
</h1>
- <group class="hidden-xs">
+ <group>
<group>
<field name="partner_id" attrs="{'invisible': [('picking_type_code', '=', 'internal')]}"/>
<field name="location_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'outgoing')]}"/>
diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py
index df6d8d7ecf9..e92b9c2ef4d 100644
--- a/addons/stock_account/models/stock.py
+++ b/addons/stock_account/models/stock.py
@@ -179,6 +179,12 @@ class StockMove(models.Model):
to_refund = fields.Boolean(string="To Refund (update SO/PO)",
help='Trigger a decrease of the delivered/received quantity in the associated Sale Order/Purchase Order')
+ def _set_default_price_moves(self):
+ # When the cost method is in real or average price, the price can be set to 0.0 on the PO
+ # So the price doesn't have to be updated
+ moves = super(StockMove, self)._set_default_price_moves()
+ return moves.filtered(lambda m: m.product_id.cost_method not in ('real', 'average'))
+
@api.multi
def action_done(self):
self.product_price_update_before_done()
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index d4a0dc8907d..11d1ed98b57 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -599,9 +599,13 @@ class WebClient(http.Controller):
return odoo.service.common.exp_version()
@http.route('/web/tests', type='http', auth="none")
- def index(self, mod=None, **kwargs):
+ def test_suite(self, mod=None, **kwargs):
return request.render('web.qunit_suite')
+ @http.route('/web/benchmarks', type='http', auth="none")
+ def benchmarks(self, mod=None, **kwargs):
+ return request.render('web.benchmark_suite')
+
class Proxy(http.Controller):
diff --git a/addons/web/doc/guidelines.rst b/addons/web/doc/guidelines.rst
index 91e1e513a05..8721d372f5b 100644
--- a/addons/web/doc/guidelines.rst
+++ b/addons/web/doc/guidelines.rst
@@ -123,6 +123,7 @@ you should use:
*
* @override method from field manager mixin
* @param {string} id
+ * @returns {Deferred}
*/
_confirmSave: function (id) {
diff --git a/addons/web/static/lib/benchmarkjs/LICENSE b/addons/web/static/lib/benchmarkjs/LICENSE
new file mode 100644
index 00000000000..65d92b588da
--- /dev/null
+++ b/addons/web/static/lib/benchmarkjs/LICENSE
@@ -0,0 +1,22 @@
+Copyright 2010-2016 Mathias Bynens <https://mathiasbynens.be/>
+Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
+Modified by John-David Dalton <http://allyoucanleet.com/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/addons/web/static/lib/benchmarkjs/benchmark.js b/addons/web/static/lib/benchmarkjs/benchmark.js
new file mode 100644
index 00000000000..efab8f68317
--- /dev/null
+++ b/addons/web/static/lib/benchmarkjs/benchmark.js
@@ -0,0 +1,2824 @@
+/*!
+ * Benchmark.js <https://benchmarkjs.com/>
+ * Copyright 2010-2016 Mathias Bynens <https://mths.be/>
+ * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
+ * Modified by John-David Dalton <http://allyoucanleet.com/>
+ * Available under MIT license <https://mths.be/mit>
+ */
+;(function() {
+ 'use strict';
+
+ /** Used as a safe reference for `undefined` in pre ES5 environments. */
+ var undefined;
+
+ /** Used to determine if values are of the language type Object. */
+ var objectTypes = {
+ 'function': true,
+ 'object': true
+ };
+
+ /** Used as a reference to the global object. */
+ var root = (objectTypes[typeof window] && window) || this;
+
+ /** Detect free variable `define`. */
+ var freeDefine = typeof define == 'function' && typeof define.amd == 'object' && define.amd && define;
+
+ /** Detect free variable `exports`. */
+ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+
+ /** Detect free variable `module`. */
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+ /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
+ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
+ if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
+ root = freeGlobal;
+ }
+
+ /** Detect free variable `require`. */
+ var freeRequire = typeof require == 'function' && require;
+
+ /** Used to assign each benchmark an incremented id. */
+ var counter = 0;
+
+ /** Detect the popular CommonJS extension `module.exports`. */
+ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
+
+ /** Used to detect primitive types. */
+ var rePrimitive = /^(?:boolean|number|string|undefined)$/;
+
+ /** Used to make every compiled test unique. */
+ var uidCounter = 0;
+
+ /** Used to assign default `context` object properties. */
+ var contextProps = [
+ 'Array', 'Date', 'Function', 'Math', 'Object', 'RegExp', 'String', '_',
+ 'clearTimeout', 'chrome', 'chromium', 'document', 'navigator', 'phantom',
+ 'platform', 'process', 'runtime', 'setTimeout'
+ ];
+
+ /** Used to avoid hz of Infinity. */
+ var divisors = {
+ '1': 4096,
+ '2': 512,
+ '3': 64,
+ '4': 8,
+ '5': 0
+ };
+
+ /**
+ * T-Distribution two-tailed critical values for 95% confidence.
+ * For more info see http://www.itl.nist.gov/div898/handbook/eda/section3/eda3672.htm.
+ */
+ var tTable = {
+ '1': 12.706, '2': 4.303, '3': 3.182, '4': 2.776, '5': 2.571, '6': 2.447,
+ '7': 2.365, '8': 2.306, '9': 2.262, '10': 2.228, '11': 2.201, '12': 2.179,
+ '13': 2.16, '14': 2.145, '15': 2.131, '16': 2.12, '17': 2.11, '18': 2.101,
+ '19': 2.093, '20': 2.086, '21': 2.08, '22': 2.074, '23': 2.069, '24': 2.064,
+ '25': 2.06, '26': 2.056, '27': 2.052, '28': 2.048, '29': 2.045, '30': 2.042,
+ 'infinity': 1.96
+ };
+
+ /**
+ * Critical Mann-Whitney U-values for 95% confidence.
+ * For more info see http://www.saburchill.com/IBbiology/stats/003.html.
+ */
+ var uTable = {
+ '5': [0, 1, 2],
+ '6': [1, 2, 3, 5],
+ '7': [1, 3, 5, 6, 8],
+ '8': [2, 4, 6, 8, 10, 13],
+ '9': [2, 4, 7, 10, 12, 15, 17],
+ '10': [3, 5, 8, 11, 14, 17, 20, 23],
+ '11': [3, 6, 9, 13, 16, 19, 23, 26, 30],
+ '12': [4, 7, 11, 14, 18, 22, 26, 29, 33, 37],
+ '13': [4, 8, 12, 16, 20, 24, 28, 33, 37, 41, 45],
+ '14': [5, 9, 13, 17, 22, 26, 31, 36, 40, 45, 50, 55],
+ '15': [5, 10, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64],
+ '16': [6, 11, 15, 21, 26, 31, 37, 42, 47, 53, 59, 64, 70, 75],
+ '17': [6, 11, 17, 22, 28, 34, 39, 45, 51, 57, 63, 67, 75, 81, 87],
+ '18': [7, 12, 18, 24, 30, 36, 42, 48, 55, 61, 67, 74, 80, 86, 93, 99],
+ '19': [7, 13, 19, 25, 32, 38, 45, 52, 58, 65, 72, 78, 85, 92, 99, 106, 113],
+ '20': [8, 14, 20, 27, 34, 41, 48, 55, 62, 69, 76, 83, 90, 98, 105, 112, 119, 127],
+ '21': [8, 15, 22, 29, 36, 43, 50, 58, 65, 73, 80, 88, 96, 103, 111, 119, 126, 134, 142],
+ '22': [9, 16, 23, 30, 38, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 150, 158],
+ '23': [9, 17, 24, 32, 40, 48, 56, 64, 73, 81, 89, 98, 106, 115, 123, 132, 140, 149, 157, 166, 175],
+ '24': [10, 17, 25, 33, 42, 50, 59, 67, 76, 85, 94, 102, 111, 120, 129, 138, 147, 156, 165, 174, 183, 192],
+ '25': [10, 18, 27, 35, 44, 53, 62, 71, 80, 89, 98, 107, 117, 126, 135, 145, 154, 163, 173, 182, 192, 201, 211],
+ '26': [11, 19, 28, 37, 46, 55, 64, 74, 83, 93, 102, 112, 122, 132, 141, 151, 161, 171, 181, 191, 200, 210, 220, 230],
+ '27': [11, 20, 29, 38, 48, 57, 67, 77, 87, 97, 107, 118, 125, 138, 147, 158, 168, 178, 188, 199, 209, 219, 230, 240, 250],
+ '28': [12, 21, 30, 40, 50, 60, 70, 80, 90, 101, 111, 122, 132, 143, 154, 164, 175, 186, 196, 207, 218, 228, 239, 250, 261, 272],
+ '29': [13, 22, 32, 42, 52, 62, 73, 83, 94, 105, 116, 127, 138, 149, 160, 171, 182, 193, 204, 215, 226, 238, 249, 260, 271, 282, 294],
+ '30': [13, 23, 33, 43, 54, 65, 76, 87, 98, 109, 120, 131, 143, 154, 166, 177, 189, 200, 212, 223, 235, 247, 258, 270, 282, 293, 305, 317]
+ };
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Create a new `Benchmark` function using the given `context` object.
+ *
+ * @static
+ * @memberOf Benchmark
+ * @param {Object} [context=root] The context object.
+ * @returns {Function} Returns a new `Benchmark` function.
+ */
+ function runInContext(context) {
+ // Exit early if unable to acquire lodash.
+ var _ = context && context._ || require('lodash') || root._;
+ if (!_) {
+ Benchmark.runInContext = runInContext;
+ return Benchmark;
+ }
+ // Avoid issues with some ES3 environments that attempt to use values, named
+ // after built-in constructors like `Object`, for the creation of literals.
+ // ES5 clears this up by stating that literals must use built-in constructors.
+ // See http://es5.github.io/#x11.1.5.
+ context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
+
+ /** Native constructor references. */
+ var Array = context.Array,
+ Date = context.Date,
+ Function = context.Function,
+ Math = context.Math,
+ Object = context.Object,
+ RegExp = context.RegExp,
+ String = context.String;
+
+ /** Used for `Array` and `Object` method references. */
+ var arrayRef = [],
+ objectProto = Object.prototype;
+
+ /** Native method shortcuts. */
+ var abs = Math.abs,
+ clearTimeout = context.clearTimeout,
+ floor = Math.floor,
+ log = Math.log,
+ max = Math.max,
+ min = Math.min,
+ pow = Math.pow,
+ push = arrayRef.push,
+ setTimeout = context.setTimeout,
+ shift = arrayRef.shift,
+ slice = arrayRef.slice,
+ sqrt = Math.sqrt,
+ toString = objectProto.toString,
+ unshift = arrayRef.unshift;
+
+ /** Used to avoid inclusion in Browserified bundles. */
+ var req = require;
+
+ /** Detect DOM document object. */
+ var doc = isHostType(context, 'document') && context.document;
+
+ /** Used to access Wade Simmons' Node.js `microtime` module. */
+ var microtimeObject = req('microtime');
+
+ /** Used to access Node.js's high resolution timer. */
+ var processObject = isHostType(context, 'process') && context.process;
+
+ /** Used to prevent a `removeChild` memory leak in IE < 9. */
+ var trash = doc && doc.createElement('div');
+
+ /** Used to integrity check compiled tests. */
+ var uid = 'uid' + _.now();
+
+ /** Used to avoid infinite recursion when methods call each other. */
+ var calledBy = {};
+
+ /**
+ * An object used to flag environments/features.
+ *
+ * @static
+ * @memberOf Benchmark
+ * @type Object
+ */
+ var support = {};
+
+ (function() {
+
+ /**
+ * Detect if running in a browser environment.
+ *
+ * @memberOf Benchmark.support
+ * @type boolean
+ */
+ support.browser = doc && isHostType(context, 'navigator') && !isHostType(context, 'phantom');
+
+ /**
+ * Detect if the Timers API exists.
+ *
+ * @memberOf Benchmark.support
+ * @type boolean
+ */
+ support.timeout = isHostType(context, 'setTimeout') && isHostType(context, 'clearTimeout');
+
+ /**
+ * Detect if function decompilation is support.
+ *
+ * @name decompilation
+ * @memberOf Benchmark.support
+ * @type boolean
+ */
+ try {
+ // Safari 2.x removes commas in object literals from `Function#toString` results.
+ // See http://webk.it/11609 for more details.
+ // Firefox 3.6 and Opera 9.25 strip grouping parentheses from `Function#toString` results.
+ // See http://bugzil.la/559438 for more details.
+ support.decompilation = Function(
+ ('return (' + (function(x) { return { 'x': '' + (1 + x) + '', 'y': 0 }; }) + ')')
+ // Avoid issues with code added by Istanbul.
+ .replace(/__cov__[^;]+;/g, '')
+ )()(0).x === '1';
+ } catch(e) {
+ support.decompilation = false;
+ }
+ }());
+
+ /**
+ * Timer object used by `clock()` and `Deferred#resolve`.
+ *
+ * @private
+ * @type Object
+ */
+ var timer = {
+
+ /**
+ * The timer namespace object or constructor.
+ *
+ * @private
+ * @memberOf timer
+ * @type {Function|Object}
+ */
+ 'ns': Date,
+
+ /**
+ * Starts the deferred timer.
+ *
+ * @private
+ * @memberOf timer
+ * @param {Object} deferred The deferred instance.
+ */
+ 'start': null, // Lazy defined in `clock()`.
+
+ /**
+ * Stops the deferred timer.
+ *
+ * @private
+ * @memberOf timer
+ * @param {Object} deferred The deferred instance.
+ */
+ 'stop': null // Lazy defined in `clock()`.
+ };
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The Benchmark constructor.
+ *
+ * Note: The Benchmark constructor exposes a handful of lodash methods to
+ * make working with arrays, collections, and objects easier. The lodash
+ * methods are:
+ * [`each/forEach`](https://lodash.com/docs#forEach), [`forOwn`](https://lodash.com/docs#forOwn),
+ * [`has`](https://lodash.com/docs#has), [`indexOf`](https://lodash.com/docs#indexOf),
+ * [`map`](https://lodash.com/docs#map), and [`reduce`](https://lodash.com/docs#reduce)
+ *
+ * @constructor
+ * @param {string} name A name to identify the benchmark.
+ * @param {Function|string} fn The test to benchmark.
+ * @param {Object} [options={}] Options object.
+ * @example
+ *
+ * // basic usage (the `new` operator is optional)
+ * var bench = new Benchmark(fn);
+ *
+ * // or using a name first
+ * var bench = new Benchmark('foo', fn);
+ *
+ * // or with options
+ * var bench = new Benchmark('foo', fn, {
+ *
+ * // displayed by `Benchmark#toString` if `name` is not available
+ * 'id': 'xyz',
+ *
+ * // called when the benchmark starts running
+ * 'onStart': onStart,
+ *
+ * // called after each run cycle
+ * 'onCycle': onCycle,
+ *
+ * // called when aborted
+ * 'onAbort': onAbort,
+ *
+ * // called when a test errors
+ * 'onError': onError,
+ *
+ * // called when reset
+ * 'onReset': onReset,
+ *
+ * // called when the benchmark completes running
+ * 'onComplete': onComplete,
+ *
+ * // compiled/called before the test loop
+ * 'setup': setup,
+ *
+ * // compiled/called after the test loop
+ * 'teardown': teardown
+ * });
+ *
+ * // or name and options
+ * var bench = new Benchmark('foo', {
+ *
+ * // a flag to indicate the benchmark is deferred
+ * 'defer': true,
+ *
+ * // benchmark test function
+ * 'fn': function(deferred) {
+ * // call `Deferred#resolve` when the deferred test is finished
+ * deferred.resolve();
+ * }
+ * });
+ *
+ * // or options only
+ * var bench = new Benchmark({
+ *
+ * // benchmark name
+ * 'name': 'foo',
+ *
+ * // benchmark test as a string
+ * 'fn': '[1,2,3,4].sort()'
+ * });
+ *
+ * // a test's `this` binding is set to the benchmark instance
+ * var bench = new Benchmark('foo', function() {
+ * 'My name is '.concat(this.name); // "My name is foo"
+ * });
+ */
+ function Benchmark(name, fn, options) {
+ var bench = this;
+
+ // Allow instance creation without the `new` operator.
+ if (!(bench instanceof Benchmark)) {
+ return new Benchmark(name, fn, options);
+ }
+ // Juggle arguments.
+ if (_.isPlainObject(name)) {
+ // 1 argument (options).
+ options = name;
+ }
+ else if (_.isFunction(name)) {
+ // 2 arguments (fn, options).
+ options = fn;
+ fn = name;
+ }
+ else if (_.isPlainObject(fn)) {
+ // 2 arguments (name, options).
+ options = fn;
+ fn = null;
+ bench.name = name;
+ }
+ else {
+ // 3 arguments (name, fn [, options]).
+ bench.name = name;
+ }
+ setOptions(bench, options);
+
+ bench.id || (bench.id = ++counter);
+ bench.fn == null && (bench.fn = fn);
+
+ bench.stats = cloneDeep(bench.stats);
+ bench.times = cloneDeep(bench.times);
+ }
+
+ /**
+ * The Deferred constructor.
+ *
+ * @constructor
+ * @memberOf Benchmark
+ * @param {Object} clone The cloned benchmark instance.
+ */
+ function Deferred(clone) {
+ var deferred = this;
+ if (!(deferred instanceof Deferred)) {
+ return new Deferred(clone);
+ }
+ deferred.benchmark = clone;
+ clock(deferred);
+ }
+
+ /**
+ * The Event constructor.
+ *
+ * @constructor
+ * @memberOf Benchmark
+ * @param {Object|string} type The event type.
+ */
+ function Event(type) {
+ var event = this;
+ if (type instanceof Event) {
+ return type;
+ }
+ return (event instanceof Event)
+ ? _.assign(event, { 'timeStamp': _.now() }, typeof type == 'string' ? { 'type': type } : type)
+ : new Event(type);
+ }
+
+ /**
+ * The Suite constructor.
+ *
+ * Note: Each Suite instance has a handful of wrapped lodash methods to
+ * make working with Suites easier. The wrapped lodash methods are:
+ * [`each/forEach`](https://lodash.com/docs#forEach), [`indexOf`](https://lodash.com/docs#indexOf),
+ * [`map`](https://lodash.com/docs#map), and [`reduce`](https://lodash.com/docs#reduce)
+ *
+ * @constructor
+ * @memberOf Benchmark
+ * @param {string} name A name to identify the suite.
+ * @param {Object} [options={}] Options object.
+ * @example
+ *
+ * // basic usage (the `new` operator is optional)
+ * var suite = new Benchmark.Suite;
+ *
+ * // or using a name first
+ * var suite = new Benchmark.Suite('foo');
+ *
+ * // or with options
+ * var suite = new Benchmark.Suite('foo', {
+ *
+ * // called when the suite starts running
+ * 'onStart': onStart,
+ *
+ * // called between running benchmarks
+ * 'onCycle': onCycle,
+ *
+ * // called when aborted
+ * 'onAbort': onAbort,
+ *
+ * // called when a test errors
+ * 'onError': onError,
+ *
+ * // called when reset
+ * 'onReset': onReset,
+ *
+ * // called when the suite completes running
+ * 'onComplete': onComplete
+ * });
+ */
+ function Suite(name, options) {
+ var suite = this;
+
+ // Allow instance creation without the `new` operator.
+ if (!(suite instanceof Suite)) {
+ return new Suite(name, options);
+ }
+ // Juggle arguments.
+ if (_.isPlainObject(name)) {
+ // 1 argument (options).
+ options = name;
+ } else {
+ // 2 arguments (name [, options]).
+ suite.name = name;
+ }
+ setOptions(suite, options);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * A specialized version of `_.cloneDeep` which only clones arrays and plain
+ * objects assigning all other values by reference.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @returns {*} The cloned value.
+ */
+ var cloneDeep = _.partial(_.cloneDeepWith, _, function(value) {
+ // Only clone primitives, arrays, and plain objects.
+ if (!_.isArray(value) && !_.isPlainObject(value)) {
+ return value;
+ }
+ });
+
+ /**
+ * Creates a function from the given arguments string and body.
+ *
+ * @private
+ * @param {string} args The comma separated function arguments.
+ * @param {string} body The function body.
+ * @returns {Function} The new function.
+ */
+ function createFunction() {
+ // Lazy define.
+ createFunction = function(args, body) {
+ var result,
+ anchor = freeDefine ? freeDefine.amd : Benchmark,
+ prop = uid + 'createFunction';
+
+ runScript((freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '=function(' + args + '){' + body + '}');
+ result = anchor[prop];
+ delete anchor[prop];
+ return result;
+ };
+ // Fix JaegerMonkey bug.
+ // For more information see http://bugzil.la/639720.
+ createFunction = support.browser && (createFunction('', 'return"' + uid + '"') || _.noop)() == uid ? createFunction : Function;
+ return createFunction.apply(null, arguments);
+ }
+
+ /**
+ * Delay the execution of a function based on the benchmark's `delay` property.
+ *
+ * @private
+ * @param {Object} bench The benchmark instance.
+ * @param {Object} fn The function to execute.
+ */
+ function delay(bench, fn) {
+ bench._timerId = _.delay(fn, bench.delay * 1e3);
+ }
+
+ /**
+ * Destroys the given element.
+ *
+ * @private
+ * @param {Element} element The element to destroy.
+ */
+ function destroyElement(element) {
+ trash.appendChild(element);
+ trash.innerHTML = '';
+ }
+
+ /**
+ * Gets the name of the first argument from a function's source.
+ *
+ * @private
+ * @param {Function} fn The function.
+ * @returns {string} The argument name.
+ */
+ function getFirstArgument(fn) {
+ return (!_.has(fn, 'toString') &&
+ (/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(fn) || 0)[1]) || '';
+ }
+
+ /**
+ * Computes the arithmetic mean of a sample.
+ *
+ * @private
+ * @param {Array} sample The sample.
+ * @returns {number} The mean.
+ */
+ function getMean(sample) {
+ return (_.reduce(sample, function(sum, x) {
+ return sum + x;
+ }) / sample.length) || 0;
+ }
+
+ /**
+ * Gets the source code of a function.
+ *
+ * @private
+ * @param {Function} fn The function.
+ * @returns {string} The function's source code.
+ */
+ function getSource(fn) {
+ var result = '';
+ if (isStringable(fn)) {
+ result = String(fn);
+ } else if (support.decompilation) {
+ // Escape the `{` for Firefox 1.
+ result = _.result(/^[^{]+\{([\s\S]*)\}\s*$/.exec(fn), 1);
+ }
+ // Trim string.
+ result = (result || '').replace(/^\s+|\s+$/g, '');
+
+ // Detect strings containing only the "use strict" directive.
+ return /^(?:\/\*+[\w\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result)
+ ? ''
+ : result;
+ }
+
+ /**
+ * Checks if an object is of the specified class.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {string} name The name of the class.
+ * @returns {boolean} Returns `true` if the value is of the specified class, else `false`.
+ */
+ function isClassOf(value, name) {
+ return value != null && toString.call(value) == '[object ' + name + ']';
+ }
+
+ /**
+ * Host objects can return type values that are different from their actual
+ * data type. The objects we are concerned with usually return non-primitive
+ * types of "object", "function", or "unknown".
+ *
+ * @private
+ * @param {*} object The owner of the property.
+ * @param {string} property The property to check.
+ * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
+ */
+ function isHostType(object, property) {
+ if (object == null) {
+ return false;
+ }
+ var type = typeof object[property];
+ return !rePrimitive.test(type) && (type != 'object' || !!object[property]);
+ }
+
+ /**
+ * Checks if a value can be safely coerced to a string.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if the value can be coerced, else `false`.
+ */
+ function isStringable(value) {
+ return _.isString(value) || (_.has(value, 'toString') && _.isFunction(value.toString));
+ }
+
+ /**
+ * A wrapper around `require` to suppress `module missing` errors.
+ *
+ * @private
+ * @param {string} id The module id.
+ * @returns {*} The exported module or `null`.
+ */
+ function require(id) {
+ try {
+ var result = freeExports && freeRequire(id);
+ } catch(e) {}
+ return result || null;
+ }
+
+ /**
+ * Runs a snippet of JavaScript via script injection.
+ *
+ * @private
+ * @param {string} code The code to run.
+ */
+ function runScript(code) {
+ var anchor = freeDefine ? define.amd : Benchmark,
+ script = doc.createElement('script'),
+ sibling = doc.getElementsByTagName('script')[0],
+ parent = sibling.parentNode,
+ prop = uid + 'runScript',
+ prefix = '(' + (freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '||function(){})();';
+
+ // Firefox 2.0.0.2 cannot use script injection as intended because it executes
+ // asynchronously, but that's OK because script injection is only used to avoid
+ // the previously commented JaegerMonkey bug.
+ try {
+ // Remove the inserted script *before* running the code to avoid differences
+ // in the expected script element count/order of the document.
+ script.appendChild(doc.createTextNode(prefix + code));
+ anchor[prop] = function() { destroyElement(script); };
+ } catch(e) {
+ parent = parent.cloneNode(false);
+ sibling = null;
+ script.text = code;
+ }
+ parent.insertBefore(script, sibling);
+ delete anchor[prop];
+ }
+
+ /**
+ * A helper function for setting options/event handlers.
+ *
+ * @private
+ * @param {Object} object The benchmark or suite instance.
+ * @param {Object} [options={}] Options object.
+ */
+ function setOptions(object, options) {
+ options = object.options = _.assign({}, cloneDeep(object.constructor.options), cloneDeep(options));
+
+ _.forOwn(options, function(value, key) {
+ if (value != null) {
+ // Add event listeners.
+ if (/^on[A-Z]/.test(key)) {
+ _.each(key.split(' '), function(key) {
+ object.on(key.slice(2).toLowerCase(), value);
+ });
+ } else if (!_.has(object, key)) {
+ object[key] = cloneDeep(value);
+ }
+ }
+ });
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Handles cycling/completing the deferred benchmark.
+ *
+ * @memberOf Benchmark.Deferred
+ */
+ function resolve() {
+ var deferred = this,
+ clone = deferred.benchmark,
+ bench = clone._original;
+
+ if (bench.aborted) {
+ // cycle() -> clone cycle/complete event -> compute()'s invoked bench.run() cycle/complete.
+ deferred.teardown();
+ clone.running = false;
+ cycle(deferred);
+ }
+ else if (++deferred.cycles < clone.count) {
+ clone.compiled.call(deferred, context, timer);
+ }
+ else {
+ timer.stop(deferred);
+ deferred.teardown();
+ delay(clone, function() { cycle(deferred); });
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * A generic `Array#filter` like method.
+ *
+ * @static
+ * @memberOf Benchmark
+ * @param {Array} array The array to iterate over.
+ * @param {Function|string} callback The function/alias called per iteration.
+ * @returns {Array} A new array of values that passed callback filter.
+ * @example
+ *
+ * // get odd numbers
+ * Benchmark.filter([1, 2, 3, 4, 5], function(n) {
+ * return n % 2;
+ * }); // -> [1, 3, 5];
+ *
+ * // get fastest benchmarks
+ * Benchmark.filter(benches, 'fastest');
+ *
+ * // get slowest benchmarks
+ * Benchmark.filter(benches, 'slowest');
+ *
+ * // get benchmarks that completed without erroring
+ * Benchmark.filter(benches, 'successful');
+ */
+ function filter(array, callback) {
+ if (callback === 'successful') {
+ // Callback to exclude those that are errored, unrun, or have hz of Infinity.
+ callback = function(bench) {
+ return bench.cycles && _.isFinite(bench.hz) && !bench.error;
+ };
+ }
+ else if (callback === 'fastest' || callback === 'slowest') {
+ // Get successful, sort by period + margin of error, and filter fastest/slowest.
+ var result = filter(array, 'successful').sort(function(a, b) {
+ a = a.stats; b = b.stats;
+ return (a.mean + a.moe > b.mean + b.moe ? 1 : -1) * (callback === 'fastest' ? 1 : -1);
+ });
+
+ return _.filter(result, function(bench) {
+ return result[0].compare(bench) == 0;
+ });
+ }
+ return _.filter(array, callback);
+ }
+
+ /**
+ * Converts a number to a more readable comma-separated string representation.
+ *
+ * @static
+ * @memberOf Benchmark
+ * @param {number} number The number to convert.
+ * @returns {string} The more readable string representation.
+ */
+ function formatNumber(number) {
+ number = String(number).split('.');
+ return number[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') +
+ (number[1] ? '.' + number[1] : '');
+ }
+
+ /**
+ * Invokes a method on all items in an array.
+ *
+ * @static
+ * @memberOf Benchmark
+ * @param {Array} benches Array of benchmarks to iterate over.
+ * @param {Object|string} name The name of the method to invoke OR options object.
+ * @param {...*} [args] Arguments to invoke the method with.
+ * @returns {Array} A new array of values returned from each method invoked.
+ * @example
+ *
+ * // invoke `reset` on all benchmarks
+ * Benchmark.invoke(benches, 'reset');
+ *
+ * // invoke `emit` with arguments
+ * Benchmark.invoke(benches, 'emit', 'complete', listener);
+ *
+ * // invoke `run(true)`, treat benchmarks as a queue, and register invoke callbacks
+ * Benchmark.invoke(benches, {
+ *
+ * // invoke the `run` method
+ * 'name': 'run',
+ *
+ * // pass a single argument
+ * 'args': true,
+ *
+ * // treat as queue, removing benchmarks from front of `benches` until empty
+ * 'queued': true,
+ *
+ * // called before any benchmarks have been invoked.
+ * 'onStart': onStart,
+ *
+ * // called between invoking benchmarks
+ * 'onCycle': onCycle,
+ *
+ * // called after all benchmarks have been invoked.
+ * 'onComplete': onComplete
+ * });
+ */
+ function invoke(benches, name) {
+ var args,
+ bench,
+ queued,
+ index = -1,
+ eventProps = { 'currentTarget': benches },
+ options = { 'onStart': _.noop, 'onCycle': _.noop, 'onComplete': _.noop },
+ result = _.toArray(benches);
+
+ /**
+ * Invokes the method of the current object and if synchronous, fetches the next.
+ */
+ function execute() {
+ var listeners,
+ async = isAsync(bench);
+
+ if (async) {
+ // Use `getNext` as the first listener.
+ bench.on('complete', getNext);
+ listeners = bench.events.complete;
+ listeners.splice(0, 0, listeners.pop());
+ }
+ // Execute method.
+ result[index] = _.isFunction(bench && bench[name]) ? bench[name].apply(bench, args) : undefined;
+ // If synchronous return `true` until finished.
+ return !async && getNext();
+ }
+
+ /**
+ * Fetches the next bench or executes `onComplete` callback.
+ */
+ function getNext(event) {
+ var cycleEvent,
+ last = bench,
+ async = isAsync(last);
+
+ if (async) {
+ last.off('complete', getNext);
+ last.emit('complete');
+ }
+ // Emit "cycle" event.
+ eventProps.type = 'cycle';
+ eventProps.target = last;
+ cycleEvent = Event(eventProps);
+ options.onCycle.call(benches, cycleEvent);
+
+ // Choose next benchmark if not exiting early.
+ if (!cycleEvent.aborted && raiseIndex() !== false) {
+ bench = queued ? benches[0] : result[index];
+ if (isAsync(bench)) {
+ delay(bench, execute);
+ }
+ else if (async) {
+ // Resume execution if previously asynchronous but now synchronous.
+ while (execute()) {}
+ }
+ else {
+ // Continue synchronous execution.
+ return true;
+ }
+ } else {
+ // Emit "complete" event.
+ eventProps.type = 'complete';
+ options.onComplete.call(benches, Event(eventProps));
+ }
+ // When used as a listener `event.aborted = true` will cancel the rest of
+ // the "complete" listeners because they were already called above and when
+ // used as part of `getNext` the `return false` will exit the execution while-loop.
+ if (event) {
+ event.aborted = true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Checks if invoking `Benchmark#run` with asynchronous cycles.
+ */
+ function isAsync(object) {
+ // Avoid using `instanceof` here because of IE memory leak issues with host objects.
+ var async = args[0] && args[0].async;
+ return name == 'run' && (object instanceof Benchmark) &&
+ ((async == null ? object.options.async : async) && support.timeout || object.defer);
+ }
+
+ /**
+ * Raises `index` to the next defined index or returns `false`.
+ */
+ function raiseIndex() {
+ index++;
+
+ // If queued remove the previous bench.
+ if (queued && index > 0) {
+ shift.call(benches);
+ }
+ // If we reached the last index then return `false`.
+ return (queued ? benches.length : index < result.length)
+ ? index
+ : (index = false);
+ }
+ // Juggle arguments.
+ if (_.isString(name)) {
+ // 2 arguments (array, name).
+ args = slice.call(arguments, 2);
+ } else {
+ // 2 arguments (array, options).
+ options = _.assign(options, name);
+ name = options.name;
+ args = _.isArray(args = 'args' in options ? options.args : []) ? args : [args];
+ queued = options.queued;
+ }
+ // Start iterating over the array.
+ if (raiseIndex() !== false) {
+ // Emit "start" event.
+ bench = result[index];
+ eventProps.type = 'start';
+ eventProps.target = bench;
+ options.onStart.call(benches, Event(eventProps));
+
+ // End early if the suite was aborted in an "onStart" listener.
+ if (name == 'run' && (benches instanceof Suite) && benches.aborted) {
+ // Emit "cycle" event.
+ eventProps.type = 'cycle';
+ options.onCycle.call(benches, Event(eventProps));
+ // Emit "complete" event.
+ eventProps.type = 'complete';
+ options.onComplete.call(benches, Event(eventProps));
+ }
+ // Start method execution.
+ else {
+ if (isAsync(bench)) {
+ delay(bench, execute);
+ } else {
+ while (execute()) {}
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates a string of joined array values or object key-value pairs.
+ *
+ * @static
+ * @memberOf Benchmark
+ * @param {Array|Object} object The object to operate on.
+ * @param {string} [separator1=','] The separator used between key-value pairs.
+ * @param {string} [separator2=': '] The separator used between keys and values.
+ * @returns {string} The joined result.
+ */
+ function join(object, separator1, separator2) {
+ var result = [],
+ length = (object = Object(object)).length,
+ arrayLike = length === length >>> 0;
+
+ separator2 || (separator2 = ': ');
+ _.each(object, function(value, key) {
+ result.push(arrayLike ? value : key + separator2 + value);
+ });
+ return result.join(separator1 || ',');
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Aborts all benchmarks in the suite.
+ *
+ * @name abort
+ * @memberOf Benchmark.Suite
+ * @returns {Object} The suite instance.
+ */
+ function abortSuite() {
+ var event,
+ suite = this,
+ resetting = calledBy.resetSuite;
+
+ if (suite.running) {
+ event = Event('abort');
+ suite.emit(event);
+ if (!event.cancelled || resetting) {
+ // Avoid infinite recursion.
+ calledBy.abortSuite = true;
+ suite.reset();
+ delete calledBy.abortSuite;
+
+ if (!resetting) {
+ suite.aborted = true;
+ invoke(suite, 'abort');
+ }
+ }
+ }
+ return suite;
+ }
+
+ /**
+ * Adds a test to the benchmark suite.
+ *
+ * @memberOf Benchmark.Suite
+ * @param {string} name A name to identify the benchmark.
+ * @param {Function|string} fn The test to benchmark.
+ * @param {Object} [options={}] Options object.
+ * @returns {Object} The suite instance.
+ * @example
+ *
+ * // basic usage
+ * suite.add(fn);
+ *
+ * // or using a name first
+ * suite.add('foo', fn);
+ *
+ * // or with options
+ * suite.add('foo', fn, {
+ * 'onCycle': onCycle,
+ * 'onComplete': onComplete
+ * });
+ *
+ * // or name and options
+ * suite.add('foo', {
+ * 'fn': fn,
+ * 'onCycle': onCycle,
+ * 'onComplete': onComplete
+ * });
+ *
+ * // or options only
+ * suite.add({
+ * 'name': 'foo',
+ * 'fn': fn,
+ * 'onCycle': onCycle,
+ * 'onComplete': onComplete
+ * });
+ */
+ function add(name, fn, options) {
+ var suite = this,
+ bench = new Benchmark(name, fn, options),
+ event = Event({ 'type': 'add', 'target': bench });
+
+ if (suite.emit(event), !event.cancelled) {
+ suite.push(bench);
+ }
+ return suite;
+ }
+
+ /**
+ * Creates a new suite with cloned benchmarks.
+ *
+ * @name clone
+ * @memberOf Benchmark.Suite
+ * @param {Object} options Options object to overwrite cloned options.
+ * @returns {Object} The new suite instance.
+ */
+ function cloneSuite(options) {
+ var suite = this,
+ result = new suite.constructor(_.assign({}, suite.options, options));
+
+ // Copy own properties.
+ _.forOwn(suite, function(value, key) {
+ if (!_.has(result, key)) {
+ result[key] = _.isFunction(_.get(value, 'clone'))
+ ? value.clone()
+ : cloneDeep(value);
+ }
+ });
+ return result;
+ }
+
+ /**
+ * An `Array#filter` like method.
+ *
+ * @name filter
+ * @memberOf Benchmark.Suite
+ * @param {Function|string} callback The function/alias called per iteration.
+ * @returns {Object} A new suite of benchmarks that passed callback filter.
+ */
+ function filterSuite(callback) {
+ var suite = this,
+ result = new suite.constructor(suite.options);
+
+ result.push.apply(result, filter(suite, callback));
+ return result;
+ }
+
+ /**
+ * Resets all benchmarks in the suite.
+ *
+ * @name reset
+ * @memberOf Benchmark.Suite
+ * @returns {Object} The suite instance.
+ */
+ function resetSuite() {
+ var event,
+ suite = this,
+ aborting = calledBy.abortSuite;
+
+ if (suite.running && !aborting) {
+ // No worries, `resetSuite()` is called within `abortSuite()`.
+ calledBy.resetSuite = true;
+ suite.abort();
+ delete calledBy.resetSuite;
+ }
+ // Reset if the state has changed.
+ else if ((suite.aborted || suite.running) &&
+ (suite.emit(event = Event('reset')), !event.cancelled)) {
+ suite.aborted = suite.running = false;
+ if (!aborting) {
+ invoke(suite, 'reset');
+ }
+ }
+ return suite;
+ }
+
+ /**
+ * Runs the suite.
+ *
+ * @name run
+ * @memberOf Benchmark.Suite
+ * @param {Object} [options={}] Options object.
+ * @returns {Object} The suite instance.
+ * @example
+ *
+ * // basic usage
+ * suite.run();
+ *
+ * // or with options
+ * suite.run({ 'async': true, 'queued': true });
+ */
+ function runSuite(options) {
+ var suite = this;
+
+ suite.reset();
+ suite.running = true;
+ options || (options = {});
+
+ invoke(suite, {
+ 'name': 'run',
+ 'args': options,
+ 'queued': options.queued,
+ 'onStart': function(event) {
+ suite.emit(event);
+ },
+ 'onCycle': function(event) {
+ var bench = event.target;
+ if (bench.error) {
+ suite.emit({ 'type': 'error', 'target': bench });
+ }
+ suite.emit(event);
+ event.aborted = suite.aborted;
+ },
+ 'onComplete': function(event) {
+ suite.running = false;
+ suite.emit(event);
+ }
+ });
+ return suite;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Executes all registered listeners of the specified event type.
+ *
+ * @memberOf Benchmark, Benchmark.Suite
+ * @param {Object|string} type The event type or object.
+ * @param {...*} [args] Arguments to invoke the listener with.
+ * @returns {*} Returns the return value of the last listener executed.
+ */
+ function emit(type) {
+ var listeners,
+ object = this,
+ event = Event(type),
+ events = object.events,
+ args = (arguments[0] = event, arguments);
+
+ event.currentTarget || (event.currentTarget = object);
+ event.target || (event.target = object);
+ delete event.result;
+
+ if (events && (listeners = _.has(events, event.type) && events[event.type])) {
+ _.each(listeners.slice(), function(listener) {
+ if ((event.result = listener.apply(object, args)) === false) {
+ event.cancelled = true;
+ }
+ return !event.aborted;
+ });
+ }
+ return event.result;
+ }
+
+ /**
+ * Returns an array of event listeners for a given type that can be manipulated
+ * to add or remove listeners.
+ *
+ * @memberOf Benchmark, Benchmark.Suite
+ * @param {string} type The event type.
+ * @returns {Array} The listeners array.
+ */
+ function listeners(type) {
+ var object = this,
+ events = object.events || (object.events = {});
+
+ return _.has(events, type) ? events[type] : (events[type] = []);
+ }
+
+ /**
+ * Unregisters a listener for the specified event type(s),
+ * or unregisters all listeners for the specified event type(s),
+ * or unregisters all listeners for all event types.
+ *
+ * @memberOf Benchmark, Benchmark.Suite
+ * @param {string} [type] The event type.
+ * @param {Function} [listener] The function to unregister.
+ * @returns {Object} The current instance.
+ * @example
+ *
+ * // unregister a listener for an event type
+ * bench.off('cycle', listener);
+ *
+ * // unregister a listener for multiple event types
+ * bench.off('start cycle', listener);
+ *
+ * // unregister all listeners for an event type
+ * bench.off('cycle');
+ *
+ * // unregister all listeners for multiple event types
+ * bench.off('start cycle complete');
+ *
+ * // unregister all listeners for all event types
+ * bench.off();
+ */
+ function off(type, listener) {
+ var object = this,
+ events = object.events;
+
+ if (!events) {
+ return object;
+ }
+ _.each(type ? type.split(' ') : events, function(listeners, type) {
+ var index;
+ if (typeof listeners == 'string') {
+ type = listeners;
+ listeners = _.has(events, type) && events[type];
+ }
+ if (listeners) {
+ if (listener) {
+ index = _.indexOf(listeners, listener);
+ if (index > -1) {
+ listeners.splice(index, 1);
+ }
+ } else {
+ listeners.length = 0;
+ }
+ }
+ });
+ return object;
+ }
+
+ /**
+ * Registers a listener for the specified event type(s).
+ *
+ * @memberOf Benchmark, Benchmark.Suite
+ * @param {string} type The event type.
+ * @param {Function} listener The function to register.
+ * @returns {Object} The current instance.
+ * @example
+ *
+ * // register a listener for an event type
+ * bench.on('cycle', listener);
+ *
+ * // register a listener for multiple event types
+ * bench.on('start cycle', listener);
+ */
+ function on(type, listener) {
+ var object = this,
+ events = object.events || (object.events = {});
+
+ _.each(type.split(' '), function(type) {
+ (_.has(events, type)
+ ? events[type]
+ : (events[type] = [])
+ ).push(listener);
+ });
+ return object;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Aborts the benchmark without recording times.
+ *
+ * @memberOf Benchmark
+ * @returns {Object} The benchmark instance.
+ */
+ function abort() {
+ var event,
+ bench = this,
+ resetting = calledBy.reset;
+
+ if (bench.running) {
+ event = Event('abort');
+ bench.emit(event);
+ if (!event.cancelled || resetting) {
+ // Avoid infinite recursion.
+ calledBy.abort = true;
+ bench.reset();
+ delete calledBy.abort;
+
+ if (support.timeout) {
+ clearTimeout(bench._timerId);
+ delete bench._timerId;
+ }
+ if (!resetting) {
+ bench.aborted = true;
+ bench.running = false;
+ }
+ }
+ }
+ return bench;
+ }
+
+ /**
+ * Creates a new benchmark using the same test and options.
+ *
+ * @memberOf Benchmark
+ * @param {Object} options Options object to overwrite cloned options.
+ * @returns {Object} The new benchmark instance.
+ * @example
+ *
+ * var bizarro = bench.clone({
+ * 'name': 'doppelganger'
+ * });
+ */
+ function clone(options) {
+ var bench = this,
+ result = new bench.constructor(_.assign({}, bench, options));
+
+ // Correct the `options` object.
+ result.options = _.assign({}, cloneDeep(bench.options), cloneDeep(options));
+
+ // Copy own custom properties.
+ _.forOwn(bench, function(value, key) {
+ if (!_.has(result, key)) {
+ result[key] = cloneDeep(value);
+ }
+ });
+
+ return result;
+ }
+
+ /**
+ * Determines if a benchmark is faster than another.
+ *
+ * @memberOf Benchmark
+ * @param {Object} other The benchmark to compare.
+ * @returns {number} Returns `-1` if slower, `1` if faster, and `0` if indeterminate.
+ */
+ function compare(other) {
+ var bench = this;
+
+ // Exit early if comparing the same benchmark.
+ if (bench == other) {
+ return 0;
+ }
+ var critical,
+ zStat,
+ sample1 = bench.stats.sample,
+ sample2 = other.stats.sample,
+ size1 = sample1.length,
+ size2 = sample2.length,
+ maxSize = max(size1, size2),
+ minSize = min(size1, size2),
+ u1 = getU(sample1, sample2),
+ u2 = getU(sample2, sample1),
+ u = min(u1, u2);
+
+ function getScore(xA, sampleB) {
+ return _.reduce(sampleB, function(total, xB) {
+ return total + (xB > xA ? 0 : xB < xA ? 1 : 0.5);
+ }, 0);
+ }
+
+ function getU(sampleA, sampleB) {
+ return _.reduce(sampleA, function(total, xA) {
+ return total + getScore(xA, sampleB);
+ }, 0);
+ }
+
+ function getZ(u) {
+ return (u - ((size1 * size2) / 2)) / sqrt((size1 * size2 * (size1 + size2 + 1)) / 12);
+ }
+ // Reject the null hypothesis the two samples come from the
+ // same population (i.e. have the same median) if...
+ if (size1 + size2 > 30) {
+ // ...the z-stat is greater than 1.96 or less than -1.96
+ // http://www.statisticslectures.com/topics/mannwhitneyu/
+ zStat = getZ(u);
+ return abs(zStat) > 1.96 ? (u == u1 ? 1 : -1) : 0;
+ }
+ // ...the U value is less than or equal the critical U value.
+ critical = maxSize < 5 || minSize < 3 ? 0 : uTable[maxSize][minSize - 3];
+ return u <= critical ? (u == u1 ? 1 : -1) : 0;
+ }
+
+ /**
+ * Reset properties and abort if running.
+ *
+ * @memberOf Benchmark
+ * @returns {Object} The benchmark instance.
+ */
+ function reset() {
+ var bench = this;
+ if (bench.running && !calledBy.abort) {
+ // No worries, `reset()` is called within `abort()`.
+ calledBy.reset = true;
+ bench.abort();
+ delete calledBy.reset;
+ return bench;
+ }
+ var event,
+ index = 0,
+ changes = [],
+ queue = [];
+
+ // A non-recursive solution to check if properties have changed.
+ // For more information see http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4.
+ var data = {
+ 'destination': bench,
+ 'source': _.assign({}, cloneDeep(bench.constructor.prototype), cloneDeep(bench.options))
+ };
+
+ do {
+ _.forOwn(data.source, function(value, key) {
+ var changed,
+ destination = data.destination,
+ currValue = destination[key];
+
+ // Skip pseudo private properties and event listeners.
+ if (/^_|^events$|^on[A-Z]/.test(key)) {
+ return;
+ }
+ if (_.isObjectLike(value)) {
+ if (_.isArray(value)) {
+ // Check if an array value has changed to a non-array value.
+ if (!_.isArray(currValue)) {
+ changed = true;
+ currValue = [];
+ }
+ // Check if an array has changed its length.
+ if (currValue.length != value.length) {
+ changed = true;
+ currValue = currValue.slice(0, value.length);
+ currValue.length = value.length;
+ }
+ }
+ // Check if an object has changed to a non-object value.
+ else if (!_.isObjectLike(currValue)) {
+ changed = true;
+ currValue = {};
+ }
+ // Register a changed object.
+ if (changed) {
+ changes.push({ 'destination': destination, 'key': key, 'value': currValue });
+ }
+ queue.push({ 'destination': currValue, 'source': value });
+ }
+ // Register a changed primitive.
+ else if (!_.eq(currValue, value) && value !== undefined) {
+ changes.push({ 'destination': destination, 'key': key, 'value': value });
+ }
+ });
+ }
+ while ((data = queue[index++]));
+
+ // If changed emit the `reset` event and if it isn't cancelled reset the benchmark.
+ if (changes.length &&
+ (bench.emit(event = Event('reset')), !event.cancelled)) {
+ _.each(changes, function(data) {
+ data.destination[data.key] = data.value;
+ });
+ }
+ return bench;
+ }
+
+ /**
+ * Displays relevant benchmark information when coerced to a string.
+ *
+ * @name toString
+ * @memberOf Benchmark
+ * @returns {string} A string representation of the benchmark instance.
+ */
+ function toStringBench() {
+ var bench = this,
+ error = bench.error,
+ hz = bench.hz,
+ id = bench.id,
+ stats = bench.stats,
+ size = stats.sample.length,
+ pm = '\xb1',
+ result = bench.name || (_.isNaN(id) ? id : '<Test #' + id + '>');
+
+ if (error) {
+ var errorStr;
+ if (!_.isObject(error)) {
+ errorStr = String(error);
+ } else if (!_.isError(Error)) {
+ errorStr = join(error);
+ } else {
+ // Error#name and Error#message properties are non-enumerable.
+ errorStr = join(_.assign({ 'name': error.name, 'message': error.message }, error));
+ }
+ result += ': ' + errorStr;
+ }
+ else {
+ result += ' x ' + formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec ' + pm +
+ stats.rme.toFixed(2) + '% (' + size + ' run' + (size == 1 ? '' : 's') + ' sampled)';
+ }
+ return result;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Clocks the time taken to execute a test per cycle (secs).
+ *
+ * @private
+ * @param {Object} bench The benchmark instance.
+ * @returns {number} The time taken.
+ */
+ function clock() {
+ var options = Benchmark.options,
+ templateData = {},
+ timers = [{ 'ns': timer.ns, 'res': max(0.0015, getRes('ms')), 'unit': 'ms' }];
+
+ // Lazy define for hi-res timers.
+ clock = function(clone) {
+ var deferred;
+
+ if (clone instanceof Deferred) {
+ deferred = clone;
+ clone = deferred.benchmark;
+ }
+ var bench = clone._original,
+ stringable = isStringable(bench.fn),
+ count = bench.count = clone.count,
+ decompilable = stringable || (support.decompilation && (clone.setup !== _.noop || clone.teardown !== _.noop)),
+ id = bench.id,
+ name = bench.name || (typeof id == 'number' ? '<Test #' + id + '>' : id),
+ result = 0;
+
+ // Init `minTime` if needed.
+ clone.minTime = bench.minTime || (bench.minTime = bench.options.minTime = options.minTime);
+
+ // Compile in setup/teardown functions and the test loop.
+ // Create a new compiled test, instead of using the cached `bench.compiled`,
+ // to avoid potential engine optimizations enabled over the life of the test.
+ var funcBody = deferred
+ ? 'var d#=this,${fnArg}=d#,m#=d#.benchmark._original,f#=m#.fn,su#=m#.setup,td#=m#.teardown;' +
+ // When `deferred.cycles` is `0` then...
+ 'if(!d#.cycles){' +
+ // set `deferred.fn`,
+ 'd#.fn=function(){var ${fnArg}=d#;if(typeof f#=="function"){try{${fn}\n}catch(e#){f#(d#)}}else{${fn}\n}};' +
+ // set `deferred.teardown`,
+ 'd#.teardown=function(){d#.cycles=0;if(typeof td#=="function"){try{${teardown}\n}catch(e#){td#()}}else{${teardown}\n}};' +
+ // execute the benchmark's `setup`,
+ 'if(typeof su#=="function"){try{${setup}\n}catch(e#){su#()}}else{${setup}\n};' +
+ // start timer,
+ 't#.start(d#);' +
+ // and then execute `deferred.fn` and return a dummy object.
+ '}d#.fn();return{uid:"${uid}"}'
+
+ : 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count,n#=t#.ns;${setup}\n${begin};' +
+ 'while(i#--){${fn}\n}${end};${teardown}\nreturn{elapsed:r#,uid:"${uid}"}';
+
+ var compiled = bench.compiled = clone.compiled = createCompiled(bench, decompilable, deferred, funcBody),
+ isEmpty = !(templateData.fn || stringable);
+
+ try {
+ if (isEmpty) {
+ // Firefox may remove dead code from `Function#toString` results.
+ // For more information see http://bugzil.la/536085.
+ throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.');
+ }
+ else if (!deferred) {
+ // Pretest to determine if compiled code exits early, usually by a
+ // rogue `return` statement, by checking for a return object with the uid.
+ bench.count = 1;
+ compiled = decompilable && (compiled.call(bench, context, timer) || {}).uid == templateData.uid && compiled;
+ bench.count = count;
+ }
+ } catch(e) {
+ compiled = null;
+ clone.error = e || new Error(String(e));
+ bench.count = count;
+ }
+ // Fallback when a test exits early or errors during pretest.
+ if (!compiled && !deferred && !isEmpty) {
+ funcBody = (
+ stringable || (decompilable && !clone.error)
+ ? 'function f#(){${fn}\n}var r#,s#,m#=this,i#=m#.count'
+ : 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count'
+ ) +
+ ',n#=t#.ns;${setup}\n${begin};m#.f#=f#;while(i#--){m#.f#()}${end};' +
+ 'delete m#.f#;${teardown}\nreturn{elapsed:r#}';
+
+ compiled = createCompiled(bench, decompilable, deferred, funcBody);
+
+ try {
+ // Pretest one more time to check for errors.
+ bench.count = 1;
+ compiled.call(bench, context, timer);
+ bench.count = count;
+ delete clone.error;
+ }
+ catch(e) {
+ bench.count = count;
+ if (!clone.error) {
+ clone.error = e || new Error(String(e));
+ }
+ }
+ }
+ // If no errors run the full test loop.
+ if (!clone.error) {
+ compiled = bench.compiled = clone.compiled = createCompiled(bench, decompilable, deferred, funcBody);
+ result = compiled.call(deferred || bench, context, timer).elapsed;
+ }
+ return result;
+ };
+
+ /*----------------------------------------------------------------------*/
+
+ /**
+ * Creates a compiled function from the given function `body`.
+ */
+ function createCompiled(bench, decompilable, deferred, body) {
+ var fn = bench.fn,
+ fnArg = deferred ? getFirstArgument(fn) || 'deferred' : '';
+
+ templateData.uid = uid + uidCounter++;
+
+ _.assign(templateData, {
+ 'setup': decompilable ? getSource(bench.setup) : interpolate('m#.setup()'),
+ 'fn': decompilable ? getSource(fn) : interpolate('m#.fn(' + fnArg + ')'),
+ 'fnArg': fnArg,
+ 'teardown': decompilable ? getSource(bench.teardown) : interpolate('m#.teardown()')
+ });
+
+ // Use API of chosen timer.
+ if (timer.unit == 'ns') {
+ _.assign(templateData, {
+ 'begin': interpolate('s#=n#()'),
+ 'end': interpolate('r#=n#(s#);r#=r#[0]+(r#[1]/1e9)')
+ });
+ }
+ else if (timer.unit == 'us') {
+ if (timer.ns.stop) {
+ _.assign(templateData, {
+ 'begin': interpolate('s#=n#.start()'),
+ 'end': interpolate('r#=n#.microseconds()/1e6')
+ });
+ } else {
+ _.assign(templateData, {
+ 'begin': interpolate('s#=n#()'),
+ 'end': interpolate('r#=(n#()-s#)/1e6')
+ });
+ }
+ }
+ else if (timer.ns.now) {
+ _.assign(templateData, {
+ 'begin': interpolate('s#=n#.now()'),
+ 'end': interpolate('r#=(n#.now()-s#)/1e3')
+ });
+ }
+ else {
+ _.assign(templateData, {
+ 'begin': interpolate('s#=new n#().getTime()'),
+ 'end': interpolate('r#=(new n#().getTime()-s#)/1e3')
+ });
+ }
+ // Define `timer` methods.
+ timer.start = createFunction(
+ interpolate('o#'),
+ interpolate('var n#=this.ns,${begin};o#.elapsed=0;o#.timeStamp=s#')
+ );
+
+ timer.stop = createFunction(
+ interpolate('o#'),
+ interpolate('var n#=this.ns,s#=o#.timeStamp,${end};o#.elapsed=r#')
+ );
+
+ // Create compiled test.
+ return createFunction(
+ interpolate('window,t#'),
+ 'var global = window, clearTimeout = global.clearTimeout, setTimeout = global.setTimeout;\n' +
+ interpolate(body)
+ );
+ }
+
+ /**
+ * Gets the current timer's minimum resolution (secs).
+ */
+ function getRes(unit) {
+ var measured,
+ begin,
+ count = 30,
+ divisor = 1e3,
+ ns = timer.ns,
+ sample = [];
+
+ // Get average smallest measurable time.
+ while (count--) {
+ if (unit == 'us') {
+ divisor = 1e6;
+ if (ns.stop) {
+ ns.start();
+ while (!(measured = ns.microseconds())) {}
+ } else {
+ begin = ns();
+ while (!(measured = ns() - begin)) {}
+ }
+ }
+ else if (unit == 'ns') {
+ divisor = 1e9;
+ begin = (begin = ns())[0] + (begin[1] / divisor);
+ while (!(measured = ((measured = ns())[0] + (measured[1] / divisor)) - begin)) {}
+ divisor = 1;
+ }
+ else if (ns.now) {
+ begin = ns.now();
+ while (!(measured = ns.now() - begin)) {}
+ }
+ else {
+ begin = new ns().getTime();
+ while (!(measured = new ns().getTime() - begin)) {}
+ }
+ // Check for broken timers.
+ if (measured > 0) {
+ sample.push(measured);
+ } else {
+ sample.push(Infinity);
+ break;
+ }
+ }
+ // Convert to seconds.
+ return getMean(sample) / divisor;
+ }
+
+ /**
+ * Interpolates a given template string.
+ */
+ function interpolate(string) {
+ // Replaces all occurrences of `#` with a unique number and template tokens with content.
+ return _.template(string.replace(/\#/g, /\d+/.exec(templateData.uid)))(templateData);
+ }
+
+ /*----------------------------------------------------------------------*/
+
+ // Detect Chrome's microsecond timer:
+ // enable benchmarking via the --enable-benchmarking command
+ // line switch in at least Chrome 7 to use chrome.Interval
+ try {
+ if ((timer.ns = new (context.chrome || context.chromium).Interval)) {
+ timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' });
+ }
+ } catch(e) {}
+
+ // Detect Node.js's nanosecond resolution timer available in Node.js >= 0.8.
+ if (processObject && typeof (timer.ns = processObject.hrtime) == 'function') {
+ timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' });
+ }
+ // Detect Wade Simmons' Node.js `microtime` module.
+ if (microtimeObject && typeof (timer.ns = microtimeObject.now) == 'function') {
+ timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' });
+ }
+ // Pick timer with highest resolution.
+ timer = _.minBy(timers, 'res');
+
+ // Error if there are no working timers.
+ if (timer.res == Infinity) {
+ throw new Error('Benchmark.js was unable to find a working timer.');
+ }
+ // Resolve time span required to achieve a percent uncertainty of at most 1%.
+ // For more information see http://spiff.rit.edu/classes/phys273/uncert/uncert.html.
+ options.minTime || (options.minTime = max(timer.res / 2 / 0.01, 0.05));
+ return clock.apply(null, arguments);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Computes stats on benchmark results.
+ *
+ * @private
+ * @param {Object} bench The benchmark instance.
+ * @param {Object} options The options object.
+ */
+ function compute(bench, options) {
+ options || (options = {});
+
+ var async = options.async,
+ elapsed = 0,
+ initCount = bench.initCount,
+ minSamples = bench.minSamples,
+ queue = [],
+ sample = bench.stats.sample;
+
+ /**
+ * Adds a clone to the queue.
+ */
+ function enqueue() {
+ queue.push(_.assign(bench.clone(), {
+ '_original': bench,
+ 'events': {
+ 'abort': [update],
+ 'cycle': [update],
+ 'error': [update],
+ 'start': [update]
+ }
+ }));
+ }
+
+ /**
+ * Updates the clone/original benchmarks to keep their data in sync.
+ */
+ function update(event) {
+ var clone = this,
+ type = event.type;
+
+ if (bench.running) {
+ if (type == 'start') {
+ // Note: `clone.minTime` prop is inited in `clock()`.
+ clone.count = bench.initCount;
+ }
+ else {
+ if (type == 'error') {
+ bench.error = clone.error;
+ }
+ if (type == 'abort') {
+ bench.abort();
+ bench.emit('cycle');
+ } else {
+ event.currentTarget = event.target = bench;
+ bench.emit(event);
+ }
+ }
+ } else if (bench.aborted) {
+ // Clear abort listeners to avoid triggering bench's abort/cycle again.
+ clone.events.abort.length = 0;
+ clone.abort();
+ }
+ }
+
+ /**
+ * Determines if more clones should be queued or if cycling should stop.
+ */
+ function evaluate(event) {
+ var critical,
+ df,
+ mean,
+ moe,
+ rme,
+ sd,
+ sem,
+ variance,
+ clone = event.target,
+ done = bench.aborted,
+ now = _.now(),
+ size = sample.push(clone.times.period),
+ maxedOut = size >= minSamples && (elapsed += now - clone.times.timeStamp) / 1e3 > bench.maxTime,
+ times = bench.times,
+ varOf = function(sum, x) { return sum + pow(x - mean, 2); };
+
+ // Exit early for aborted or unclockable tests.
+ if (done || clone.hz == Infinity) {
+ maxedOut = !(size = sample.length = queue.length = 0);
+ }
+
+ if (!done) {
+ // Compute the sample mean (estimate of the population mean).
+ mean = getMean(sample);
+ // Compute the sample variance (estimate of the population variance).
+ variance = _.reduce(sample, varOf, 0) / (size - 1) || 0;
+ // Compute the sample standard deviation (estimate of the population standard deviation).
+ sd = sqrt(variance);
+ // Compute the standard error of the mean (a.k.a. the standard deviation of the sampling distribution of the sample mean).
+ sem = sd / sqrt(size);
+ // Compute the degrees of freedom.
+ df = size - 1;
+ // Compute the critical value.
+ critical = tTable[Math.round(df) || 1] || tTable.infinity;
+ // Compute the margin of error.
+ moe = sem * critical;
+ // Compute the relative margin of error.
+ rme = (moe / mean) * 100 || 0;
+
+ _.assign(bench.stats, {
+ 'deviation': sd,
+ 'mean': mean,
+ 'moe': moe,
+ 'rme': rme,
+ 'sem': sem,
+ 'variance': variance
+ });
+
+ // Abort the cycle loop when the minimum sample size has been collected
+ // and the elapsed time exceeds the maximum time allowed per benchmark.
+ // We don't count cycle delays toward the max time because delays may be
+ // increased by browsers that clamp timeouts for inactive tabs. For more
+ // information see https://developer.mozilla.org/en/window.setTimeout#Inactive_tabs.
+ if (maxedOut) {
+ // Reset the `initCount` in case the benchmark is rerun.
+ bench.initCount = initCount;
+ bench.running = false;
+ done = true;
+ times.elapsed = (now - times.timeStamp) / 1e3;
+ }
+ if (bench.hz != Infinity) {
+ bench.hz = 1 / mean;
+ times.cycle = mean * bench.count;
+ times.period = mean;
+ }
+ }
+ // If time permits, increase sample size to reduce the margin of error.
+ if (queue.length < 2 && !maxedOut) {
+ enqueue();
+ }
+ // Abort the `invoke` cycle when done.
+ event.aborted = done;
+ }
+
+ // Init queue and begin.
+ enqueue();
+ invoke(queue, {
+ 'name': 'run',
+ 'args': { 'async': async },
+ 'queued': true,
+ 'onCycle': evaluate,
+ 'onComplete': function() { bench.emit('complete'); }
+ });
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Cycles a benchmark until a run `count` can be established.
+ *
+ * @private
+ * @param {Object} clone The cloned benchmark instance.
+ * @param {Object} options The options object.
+ */
+ function cycle(clone, options) {
+ options || (options = {});
+
+ var deferred;
+ if (clone instanceof Deferred) {
+ deferred = clone;
+ clone = clone.benchmark;
+ }
+ var clocked,
+ cycles,
+ divisor,
+ event,
+ minTime,
+ period,
+ async = options.async,
+ bench = clone._original,
+ count = clone.count,
+ times = clone.times;
+
+ // Continue, if not aborted between cycles.
+ if (clone.running) {
+ // `minTime` is set to `Benchmark.options.minTime` in `clock()`.
+ cycles = ++clone.cycles;
+ clocked = deferred ? deferred.elapsed : clock(clone);
+ minTime = clone.minTime;
+
+ if (cycles > bench.cycles) {
+ bench.cycles = cycles;
+ }
+ if (clone.error) {
+ event = Event('error');
+ event.message = clone.error;
+ clone.emit(event);
+ if (!event.cancelled) {
+ clone.abort();
+ }
+ }
+ }
+ // Continue, if not errored.
+ if (clone.running) {
+ // Compute the time taken to complete last test cycle.
+ bench.times.cycle = times.cycle = clocked;
+ // Compute the seconds per operation.
+ period = bench.times.period = times.period = clocked / count;
+ // Compute the ops per second.
+ bench.hz = clone.hz = 1 / period;
+ // Avoid working our way up to this next time.
+ bench.initCount = clone.initCount = count;
+ // Do we need to do another cycle?
+ clone.running = clocked < minTime;
+
+ if (clone.running) {
+ // Tests may clock at `0` when `initCount` is a small number,
+ // to avoid that we set its count to something a bit higher.
+ if (!clocked && (divisor = divisors[clone.cycles]) != null) {
+ count = floor(4e6 / divisor);
+ }
+ // Calculate how many more iterations it will take to achieve the `minTime`.
+ if (count <= clone.count) {
+ count += Math.ceil((minTime - clocked) / period);
+ }
+ clone.running = count != Infinity;
+ }
+ }
+ // Should we exit early?
+ event = Event('cycle');
+ clone.emit(event);
+ if (event.aborted) {
+ clone.abort();
+ }
+ // Figure out what to do next.
+ if (clone.running) {
+ // Start a new cycle.
+ clone.count = count;
+ if (deferred) {
+ clone.compiled.call(deferred, context, timer);
+ } else if (async) {
+ delay(clone, function() { cycle(clone, options); });
+ } else {
+ cycle(clone);
+ }
+ }
+ else {
+ // Fix TraceMonkey bug associated with clock fallbacks.
+ // For more information see http://bugzil.la/509069.
+ if (support.browser) {
+ runScript(uid + '=1;delete ' + uid);
+ }
+ // We're done.
+ clone.emit('complete');
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Runs the benchmark.
+ *
+ * @memberOf Benchmark
+ * @param {Object} [options={}] Options object.
+ * @returns {Object} The benchmark instance.
+ * @example
+ *
+ * // basic usage
+ * bench.run();
+ *
+ * // or with options
+ * bench.run({ 'async': true });
+ */
+ function run(options) {
+ var bench = this,
+ event = Event('start');
+
+ // Set `running` to `false` so `reset()` won't call `abort()`.
+ bench.running = false;
+ bench.reset();
+ bench.running = true;
+
+ bench.count = bench.initCount;
+ bench.times.timeStamp = _.now();
+ bench.emit(event);
+
+ if (!event.cancelled) {
+ options = { 'async': ((options = options && options.async) == null ? bench.async : options) && support.timeout };
+
+ // For clones created within `compute()`.
+ if (bench._original) {
+ if (bench.defer) {
+ Deferred(bench);
+ } else {
+ cycle(bench, options);
+ }
+ }
+ // For original benchmarks.
+ else {
+ compute(bench, options);
+ }
+ }
+ return bench;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ // Firefox 1 erroneously defines variable and argument names of functions on
+ // the function itself as non-configurable properties with `undefined` values.
+ // The bugginess continues as the `Benchmark` constructor has an argument
+ // named `options` and Firefox 1 will not assign a value to `Benchmark.options`,
+ // making it non-writable in the process, unless it is the first property
+ // assigned by for-in loop of `_.assign()`.
+ _.assign(Benchmark, {
+
+ /**
+ * The default options copied by benchmark instances.
+ *
+ * @static
+ * @memberOf Benchmark
+ * @type Object
+ */
+ 'options': {
+
+ /**
+ * A flag to indicate that benchmark cycles will execute asynchronously
+ * by default.
+ *
+ * @memberOf Benchmark.options
+ * @type boolean
+ */
+ 'async': false,
+
+ /**
+ * A flag to indicate that the benchmark clock is deferred.
+ *
+ * @memberOf Benchmark.options
+ * @type boolean
+ */
+ 'defer': false,
+
+ /**
+ * The delay between test cycles (secs).
+ * @memberOf Benchmark.options
+ * @type number
+ */
+ 'delay': 0.005,
+
+ /**
+ * Displayed by `Benchmark#toString` when a `name` is not available
+ * (auto-generated if absent).
+ *
+ * @memberOf Benchmark.options
+ * @type string
+ */
+ 'id': undefined,
+
+ /**
+ * The default number of times to execute a test on a benchmark's first cycle.
+ *
+ * @memberOf Benchmark.options
+ * @type number
+ */
+ 'initCount': 1,
+
+ /**
+ * The maximum time a benchmark is allowed to run before finishing (secs).
+ *
+ * Note: Cycle delays aren't counted toward the maximum time.
+ *
+ * @memberOf Benchmark.options
+ * @type number
+ */
+ 'maxTime': 5,
+
+ /**
+ * The minimum sample size required to perform statistical analysis.
+ *
+ * @memberOf Benchmark.options
+ * @type number
+ */
+ 'minSamples': 5,
+
+ /**
+ * The time needed to reduce the percent uncertainty of measurement to 1% (secs).
+ *
+ * @memberOf Benchmark.options
+ * @type number
+ */
+ 'minTime': 0,
+
+ /**
+ * The name of the benchmark.
+ *
+ * @memberOf Benchmark.options
+ * @type string
+ */
+ 'name': undefined,
+
+ /**
+ * An event listener called when the benchmark is aborted.
+ *
+ * @memberOf Benchmark.options
+ * @type Function
+ */
+ 'onAbort': undefined,
+
+ /**
+ * An event listener called when the benchmark completes running.
+ *
+ * @memberOf Benchmark.options
+ * @type Function
+ */
+ 'onComplete': undefined,
+
+ /**
+ * An event listener called after each run cycle.
+ *
+ * @memberOf Benchmark.options
+ * @type Function
+ */
+ 'onCycle': undefined,
+
+ /**
+ * An event listener called when a test errors.
+ *
+ * @memberOf Benchmark.options
+ * @type Function
+ */
+ 'onError': undefined,
+
+ /**
+ * An event listener called when the benchmark is reset.
+ *
+ * @memberOf Benchmark.options
+ * @type Function
+ */
+ 'onReset': undefined,
+
+ /**
+ * An event listener called when the benchmark starts running.
+ *
+ * @memberOf Benchmark.options
+ * @type Function
+ */
+ 'onStart': undefined
+ },
+
+ /**
+ * Platform object with properties describing things like browser name,
+ * version, and operating system. See [`platform.js`](https://mths.be/platform).
+ *
+ * @static
+ * @memberOf Benchmark
+ * @type Object
+ */
+ 'platform': context.platform || require('platform') || ({
+ 'description': context.navigator && context.navigator.userAgent || null,
+ 'layout': null,
+ 'product': null,
+ 'name': null,
+ 'manufacturer': null,
+ 'os': null,
+ 'prerelease': null,
+ 'version': null,
+ 'toString': function() {
+ return this.description || '';
+ }
+ }),
+
+ /**
+ * The semantic version number.
+ *
+ * @static
+ * @memberOf Benchmark
+ * @type string
+ */
+ 'version': '2.1.4'
+ });
+
+ _.assign(Benchmark, {
+ 'filter': filter,
+ 'formatNumber': formatNumber,
+ 'invoke': invoke,
+ 'join': join,
+ 'runInContext': runInContext,
+ 'support': support
+ });
+
+ // Add lodash methods to Benchmark.
+ _.each(['each', 'forEach', 'forOwn', 'has', 'indexOf', 'map', 'reduce'], function(methodName) {
+ Benchmark[methodName] = _[methodName];
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ _.assign(Benchmark.prototype, {
+
+ /**
+ * The number of times a test was executed.
+ *
+ * @memberOf Benchmark
+ * @type number
+ */
+ 'count': 0,
+
+ /**
+ * The number of cycles performed while benchmarking.
+ *
+ * @memberOf Benchmark
+ * @type number
+ */
+ 'cycles': 0,
+
+ /**
+ * The number of executions per second.
+ *
+ * @memberOf Benchmark
+ * @type number
+ */
+ 'hz': 0,
+
+ /**
+ * The compiled test function.
+ *
+ * @memberOf Benchmark
+ * @type {Function|string}
+ */
+ 'compiled': undefined,
+
+ /**
+ * The error object if the test failed.
+ *
+ * @memberOf Benchmark
+ * @type Object
+ */
+ 'error': undefined,
+
+ /**
+ * The test to benchmark.
+ *
+ * @memberOf Benchmark
+ * @type {Function|string}
+ */
+ 'fn': undefined,
+
+ /**
+ * A flag to indicate if the benchmark is aborted.
+ *
+ * @memberOf Benchmark
+ * @type boolean
+ */
+ 'aborted': false,
+
+ /**
+ * A flag to indicate if the benchmark is running.
+ *
+ * @memberOf Benchmark
+ * @type boolean
+ */
+ 'running': false,
+
+ /**
+ * Compiled into the test and executed immediately **before** the test loop.
+ *
+ * @memberOf Benchmark
+ * @type {Function|string}
+ * @example
+ *
+ * // basic usage
+ * var bench = Benchmark({
+ * 'setup': function() {
+ * var c = this.count,
+ * element = document.getElementById('container');
+ * while (c--) {
+ * element.appendChild(document.createElement('div'));
+ * }
+ * },
+ * 'fn': function() {
+ * element.removeChild(element.lastChild);
+ * }
+ * });
+ *
+ * // compiles to something like:
+ * var c = this.count,
+ * element = document.getElementById('container');
+ * while (c--) {
+ * element.appendChild(document.createElement('div'));
+ * }
+ * var start = new Date;
+ * while (count--) {
+ * element.removeChild(element.lastChild);
+ * }
+ * var end = new Date - start;
+ *
+ * // or using strings
+ * var bench = Benchmark({
+ * 'setup': '\
+ * var a = 0;\n\
+ * (function() {\n\
+ * (function() {\n\
+ * (function() {',
+ * 'fn': 'a += 1;',
+ * 'teardown': '\
+ * }())\n\
+ * }())\n\
+ * }())'
+ * });
+ *
+ * // compiles to something like:
+ * var a = 0;
+ * (function() {
+ * (function() {
+ * (function() {
+ * var start = new Date;
+ * while (count--) {
+ * a += 1;
+ * }
+ * var end = new Date - start;
+ * }())
+ * }())
+ * }())
+ */
+ 'setup': _.noop,
+
+ /**
+ * Compiled into the test and executed immediately **after** the test loop.
+ *
+ * @memberOf Benchmark
+ * @type {Function|string}
+ */
+ 'teardown': _.noop,
+
+ /**
+ * An object of stats including mean, margin or error, and standard deviation.
+ *
+ * @memberOf Benchmark
+ * @type Object
+ */
+ 'stats': {
+
+ /**
+ * The margin of error.
+ *
+ * @memberOf Benchmark#stats
+ * @type number
+ */
+ 'moe': 0,
+
+ /**
+ * The relative margin of error (expressed as a percentage of the mean).
+ *
+ * @memberOf Benchmark#stats
+ * @type number
+ */
+ 'rme': 0,
+
+ /**
+ * The standard error of the mean.
+ *
+ * @memberOf Benchmark#stats
+ * @type number
+ */
+ 'sem': 0,
+
+ /**
+ * The sample standard deviation.
+ *
+ * @memberOf Benchmark#stats
+ * @type number
+ */
+ 'deviation': 0,
+
+ /**
+ * The sample arithmetic mean (secs).
+ *
+ * @memberOf Benchmark#stats
+ * @type number
+ */
+ 'mean': 0,
+
+ /**
+ * The array of sampled periods.
+ *
+ * @memberOf Benchmark#stats
+ * @type Array
+ */
+ 'sample': [],
+
+ /**
+ * The sample variance.
+ *
+ * @memberOf Benchmark#stats
+ * @type number
+ */
+ 'variance': 0
+ },
+
+ /**
+ * An object of timing data including cycle, elapsed, period, start, and stop.
+ *
+ * @memberOf Benchmark
+ * @type Object
+ */
+ 'times': {
+
+ /**
+ * The time taken to complete the last cycle (secs).
+ *
+ * @memberOf Benchmark#times
+ * @type number
+ */
+ 'cycle': 0,
+
+ /**
+ * The time taken to complete the benchmark (secs).
+ *
+ * @memberOf Benchmark#times
+ * @type number
+ */
+ 'elapsed': 0,
+
+ /**
+ * The time taken to execute the test once (secs).
+ *
+ * @memberOf Benchmark#times
+ * @type number
+ */
+ 'period': 0,
+
+ /**
+ * A timestamp of when the benchmark started (ms).
+ *
+ * @memberOf Benchmark#times
+ * @type number
+ */
+ 'timeStamp': 0
+ }
+ });
+
+ _.assign(Benchmark.prototype, {
+ 'abort': abort,
+ 'clone': clone,
+ 'compare': compare,
+ 'emit': emit,
+ 'listeners': listeners,
+ 'off': off,
+ 'on': on,
+ 'reset': reset,
+ 'run': run,
+ 'toString': toStringBench
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ _.assign(Deferred.prototype, {
+
+ /**
+ * The deferred benchmark instance.
+ *
+ * @memberOf Benchmark.Deferred
+ * @type Object
+ */
+ 'benchmark': null,
+
+ /**
+ * The number of deferred cycles performed while benchmarking.
+ *
+ * @memberOf Benchmark.Deferred
+ * @type number
+ */
+ 'cycles': 0,
+
+ /**
+ * The time taken to complete the deferred benchmark (secs).
+ *
+ * @memberOf Benchmark.Deferred
+ * @type number
+ */
+ 'elapsed': 0,
+
+ /**
+ * A timestamp of when the deferred benchmark started (ms).
+ *
+ * @memberOf Benchmark.Deferred
+ * @type number
+ */
+ 'timeStamp': 0
+ });
+
+ _.assign(Deferred.prototype, {
+ 'resolve': resolve
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ _.assign(Event.prototype, {
+
+ /**
+ * A flag to indicate if the emitters listener iteration is aborted.
+ *
+ * @memberOf Benchmark.Event
+ * @type boolean
+ */
+ 'aborted': false,
+
+ /**
+ * A flag to indicate if the default action is cancelled.
+ *
+ * @memberOf Benchmark.Event
+ * @type boolean
+ */
+ 'cancelled': false,
+
+ /**
+ * The object whose listeners are currently being processed.
+ *
+ * @memberOf Benchmark.Event
+ * @type Object
+ */
+ 'currentTarget': undefined,
+
+ /**
+ * The return value of the last executed listener.
+ *
+ * @memberOf Benchmark.Event
+ * @type Mixed
+ */
+ 'result': undefined,
+
+ /**
+ * The object to which the event was originally emitted.
+ *
+ * @memberOf Benchmark.Event
+ * @type Object
+ */
+ 'target': undefined,
+
+ /**
+ * A timestamp of when the event was created (ms).
+ *
+ * @memberOf Benchmark.Event
+ * @type number
+ */
+ 'timeStamp': 0,
+
+ /**
+ * The event type.
+ *
+ * @memberOf Benchmark.Event
+ * @type string
+ */
+ 'type': ''
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The default options copied by suite instances.
+ *
+ * @static
+ * @memberOf Benchmark.Suite
+ * @type Object
+ */
+ Suite.options = {
+
+ /**
+ * The name of the suite.
+ *
+ * @memberOf Benchmark.Suite.options
+ * @type string
+ */
+ 'name': undefined
+ };
+
+ /*------------------------------------------------------------------------*/
+
+ _.assign(Suite.prototype, {
+
+ /**
+ * The number of benchmarks in the suite.
+ *
+ * @memberOf Benchmark.Suite
+ * @type number
+ */
+ 'length': 0,
+
+ /**
+ * A flag to indicate if the suite is aborted.
+ *
+ * @memberOf Benchmark.Suite
+ * @type boolean
+ */
+ 'aborted': false,
+
+ /**
+ * A flag to indicate if the suite is running.
+ *
+ * @memberOf Benchmark.Suite
+ * @type boolean
+ */
+ 'running': false
+ });
+
+ _.assign(Suite.prototype, {
+ 'abort': abortSuite,
+ 'add': add,
+ 'clone': cloneSuite,
+ 'emit': emit,
+ 'filter': filterSuite,
+ 'join': arrayRef.join,
+ 'listeners': listeners,
+ 'off': off,
+ 'on': on,
+ 'pop': arrayRef.pop,
+ 'push': push,
+ 'reset': resetSuite,
+ 'run': runSuite,
+ 'reverse': arrayRef.reverse,
+ 'shift': shift,
+ 'slice': slice,
+ 'sort': arrayRef.sort,
+ 'splice': arrayRef.splice,
+ 'unshift': unshift
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ // Expose Deferred, Event, and Suite.
+ _.assign(Benchmark, {
+ 'Deferred': Deferred,
+ 'Event': Event,
+ 'Suite': Suite
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ // Add lodash methods as Suite methods.
+ _.each(['each', 'forEach', 'indexOf', 'map', 'reduce'], function(methodName) {
+ var func = _[methodName];
+ Suite.prototype[methodName] = function() {
+ var args = [this];
+ push.apply(args, arguments);
+ return func.apply(_, args);
+ };
+ });
+
+ // Avoid array-like object bugs with `Array#shift` and `Array#splice`
+ // in Firefox < 10 and IE < 9.
+ _.each(['pop', 'shift', 'splice'], function(methodName) {
+ var func = arrayRef[methodName];
+
+ Suite.prototype[methodName] = function() {
+ var value = this,
+ result = func.apply(value, arguments);
+
+ if (value.length === 0) {
+ delete value[0];
+ }
+ return result;
+ };
+ });
+
+ // Avoid buggy `Array#unshift` in IE < 8 which doesn't return the new
+ // length of the array.
+ Suite.prototype.unshift = function() {
+ var value = this;
+ unshift.apply(value, arguments);
+ return value.length;
+ };
+
+ return Benchmark;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // Export Benchmark.
+ // Some AMD build optimizers, like r.js, check for condition patterns like the following:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Define as an anonymous module so, through path mapping, it can be aliased.
+ define(['lodash', 'platform'], function(_, platform) {
+ return runInContext({
+ '_': _,
+ 'platform': platform
+ });
+ });
+ }
+ else {
+ var Benchmark = runInContext();
+
+ // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
+ if (freeExports && freeModule) {
+ // Export for Node.js.
+ if (moduleExports) {
+ (freeModule.exports = Benchmark).Benchmark = Benchmark;
+ }
+ // Export for CommonJS support.
+ freeExports.Benchmark = Benchmark;
+ }
+ else {
+ // Export to the global object.
+ root.Benchmark = Benchmark;
+ }
+ }
+}.call(this));
diff --git a/addons/web/static/lib/benchmarkjs/lodash.js b/addons/web/static/lib/benchmarkjs/lodash.js
new file mode 100644
index 00000000000..b39ddce69b3
--- /dev/null
+++ b/addons/web/static/lib/benchmarkjs/lodash.js
@@ -0,0 +1,17084 @@
+/**
+ * @license
+ * Lodash <https://lodash.com/>
+ * Copyright JS Foundation and other contributors <https://js.foundation/>
+ * Released under MIT license <https://lodash.com/license>
+ * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */
+;(function() {
+
+ /** Used as a safe reference for `undefined` in pre-ES5 environments. */
+ var undefined;
+
+ /** Used as the semantic version number. */
+ var VERSION = '4.17.4';
+
+ /** Used as the size to enable large array optimizations. */
+ var LARGE_ARRAY_SIZE = 200;
+
+ /** Error message constants. */
+ var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
+ FUNC_ERROR_TEXT = 'Expected a function';
+
+ /** Used to stand-in for `undefined` hash values. */
+ var HASH_UNDEFINED = '__lodash_hash_undefined__';
+
+ /** Used as the maximum memoize cache size. */
+ var MAX_MEMOIZE_SIZE = 500;
+
+ /** Used as the internal argument placeholder. */
+ var PLACEHOLDER = '__lodash_placeholder__';
+
+ /** Used to compose bitmasks for cloning. */
+ var CLONE_DEEP_FLAG = 1,
+ CLONE_FLAT_FLAG = 2,
+ CLONE_SYMBOLS_FLAG = 4;
+
+ /** Used to compose bitmasks for value comparisons. */
+ var COMPARE_PARTIAL_FLAG = 1,
+ COMPARE_UNORDERED_FLAG = 2;
+
+ /** Used to compose bitmasks for function metadata. */
+ var WRAP_BIND_FLAG = 1,
+ WRAP_BIND_KEY_FLAG = 2,
+ WRAP_CURRY_BOUND_FLAG = 4,
+ WRAP_CURRY_FLAG = 8,
+ WRAP_CURRY_RIGHT_FLAG = 16,
+ WRAP_PARTIAL_FLAG = 32,
+ WRAP_PARTIAL_RIGHT_FLAG = 64,
+ WRAP_ARY_FLAG = 128,
+ WRAP_REARG_FLAG = 256,
+ WRAP_FLIP_FLAG = 512;
+
+ /** Used as default options for `_.truncate`. */
+ var DEFAULT_TRUNC_LENGTH = 30,
+ DEFAULT_TRUNC_OMISSION = '...';
+
+ /** Used to detect hot functions by number of calls within a span of milliseconds. */
+ var HOT_COUNT = 800,
+ HOT_SPAN = 16;
+
+ /** Used to indicate the type of lazy iteratees. */
+ var LAZY_FILTER_FLAG = 1,
+ LAZY_MAP_FLAG = 2,
+ LAZY_WHILE_FLAG = 3;
+
+ /** Used as references for various `Number` constants. */
+ var INFINITY = 1 / 0,
+ MAX_SAFE_INTEGER = 9007199254740991,
+ MAX_INTEGER = 1.7976931348623157e+308,
+ NAN = 0 / 0;
+
+ /** Used as references for the maximum length and index of an array. */
+ var MAX_ARRAY_LENGTH = 4294967295,
+ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
+ HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
+
+ /** Used to associate wrap methods with their bit flags. */
+ var wrapFlags = [
+ ['ary', WRAP_ARY_FLAG],
+ ['bind', WRAP_BIND_FLAG],
+ ['bindKey', WRAP_BIND_KEY_FLAG],
+ ['curry', WRAP_CURRY_FLAG],
+ ['curryRight', WRAP_CURRY_RIGHT_FLAG],
+ ['flip', WRAP_FLIP_FLAG],
+ ['partial', WRAP_PARTIAL_FLAG],
+ ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
+ ['rearg', WRAP_REARG_FLAG]
+ ];
+
+ /** `Object#toString` result references. */
+ var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ asyncTag = '[object AsyncFunction]',
+ boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ domExcTag = '[object DOMException]',
+ errorTag = '[object Error]',
+ funcTag = '[object Function]',
+ genTag = '[object GeneratorFunction]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ nullTag = '[object Null]',
+ objectTag = '[object Object]',
+ promiseTag = '[object Promise]',
+ proxyTag = '[object Proxy]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ symbolTag = '[object Symbol]',
+ undefinedTag = '[object Undefined]',
+ weakMapTag = '[object WeakMap]',
+ weakSetTag = '[object WeakSet]';
+
+ var arrayBufferTag = '[object ArrayBuffer]',
+ dataViewTag = '[object DataView]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+
+ /** Used to match empty string literals in compiled template source. */
+ var reEmptyStringLeading = /\b__p \+= '';/g,
+ reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+ /** Used to match HTML entities and HTML characters. */
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
+ reUnescapedHtml = /[&<>"']/g,
+ reHasEscapedHtml = RegExp(reEscapedHtml.source),
+ reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+
+ /** Used to match template delimiters. */
+ var reEscape = /<%-([\s\S]+?)%>/g,
+ reEvaluate = /<%([\s\S]+?)%>/g,
+ reInterpolate = /<%=([\s\S]+?)%>/g;
+
+ /** Used to match property names within property paths. */
+ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
+ reIsPlainProp = /^\w*$/,
+ reLeadingDot = /^\./,
+ rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
+
+ /**
+ * Used to match `RegExp`
+ * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
+ */
+ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
+ reHasRegExpChar = RegExp(reRegExpChar.source);
+
+ /** Used to match leading and trailing whitespace. */
+ var reTrim = /^\s+|\s+$/g,
+ reTrimStart = /^\s+/,
+ reTrimEnd = /\s+$/;
+
+ /** Used to match wrap detail comments. */
+ var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
+ reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
+ reSplitDetails = /,? & /;
+
+ /** Used to match words composed of alphanumeric characters. */
+ var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
+
+ /** Used to match backslashes in property paths. */
+ var reEscapeChar = /\\(\\)?/g;
+
+ /**
+ * Used to match
+ * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
+ */
+ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+ /** Used to match `RegExp` flags from their coerced string values. */
+ var reFlags = /\w*$/;
+
+ /** Used to detect bad signed hexadecimal string values. */
+ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+
+ /** Used to detect binary string values. */
+ var reIsBinary = /^0b[01]+$/i;
+
+ /** Used to detect host constructors (Safari). */
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+ /** Used to detect octal string values. */
+ var reIsOctal = /^0o[0-7]+$/i;
+
+ /** Used to detect unsigned integer values. */
+ var reIsUint = /^(?:0|[1-9]\d*)$/;
+
+ /** Used to match Latin Unicode letters (excluding mathematical operators). */
+ var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
+
+ /** Used to ensure capturing order of template delimiters. */
+ var reNoMatch = /($^)/;
+
+ /** Used to match unescaped characters in compiled string literals. */
+ var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+
+ /** Used to compose unicode character classes. */
+ var rsAstralRange = '\\ud800-\\udfff',
+ rsComboMarksRange = '\\u0300-\\u036f',
+ reComboHalfMarksRange = '\\ufe20-\\ufe2f',
+ rsComboSymbolsRange = '\\u20d0-\\u20ff',
+ rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
+ rsDingbatRange = '\\u2700-\\u27bf',
+ rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
+ rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
+ rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
+ rsPunctuationRange = '\\u2000-\\u206f',
+ rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
+ rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
+ rsVarRange = '\\ufe0e\\ufe0f',
+ rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
+
+ /** Used to compose unicode capture groups. */
+ var rsApos = "['\u2019]",
+ rsAstral = '[' + rsAstralRange + ']',
+ rsBreak = '[' + rsBreakRange + ']',
+ rsCombo = '[' + rsComboRange + ']',
+ rsDigits = '\\d+',
+ rsDingbat = '[' + rsDingbatRange + ']',
+ rsLower = '[' + rsLowerRange + ']',
+ rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
+ rsFitz = '\\ud83c[\\udffb-\\udfff]',
+ rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
+ rsNonAstral = '[^' + rsAstralRange + ']',
+ rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
+ rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
+ rsUpper = '[' + rsUpperRange + ']',
+ rsZWJ = '\\u200d';
+
+ /** Used to compose unicode regexes. */
+ var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
+ rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
+ rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
+ rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
+ reOptMod = rsModifier + '?',
+ rsOptVar = '[' + rsVarRange + ']?',
+ rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
+ rsOrdLower = '\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)',
+ rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)',
+ rsSeq = rsOptVar + reOptMod + rsOptJoin,
+ rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
+ rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
+
+ /** Used to match apostrophes. */
+ var reApos = RegExp(rsApos, 'g');
+
+ /**
+ * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
+ * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
+ */
+ var reComboMark = RegExp(rsCombo, 'g');
+
+ /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
+ var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
+
+ /** Used to match complex or compound words. */
+ var reUnicodeWord = RegExp([
+ rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
+ rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
+ rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
+ rsUpper + '+' + rsOptContrUpper,
+ rsOrdUpper,
+ rsOrdLower,
+ rsDigits,
+ rsEmoji
+ ].join('|'), 'g');
+
+ /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
+ var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
+
+ /** Used to detect strings that need a more robust regexp to match words. */
+ var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
+
+ /** Used to assign default `context` object properties. */
+ var contextProps = [
+ 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
+ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
+ 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
+ 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
+ '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
+ ];
+
+ /** Used to make template sourceURLs easier to identify. */
+ var templateCounter = -1;
+
+ /** Used to identify `toStringTag` values of typed arrays. */
+ var typedArrayTags = {};
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
+ typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
+ typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
+ typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
+ typedArrayTags[uint32Tag] = true;
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
+ typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
+ typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
+ typedArrayTags[errorTag] = typedArrayTags[funcTag] =
+ typedArrayTags[mapTag] = typedArrayTags[numberTag] =
+ typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
+ typedArrayTags[setTag] = typedArrayTags[stringTag] =
+ typedArrayTags[weakMapTag] = false;
+
+ /** Used to identify `toStringTag` values supported by `_.clone`. */
+ var cloneableTags = {};
+ cloneableTags[argsTag] = cloneableTags[arrayTag] =
+ cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
+ cloneableTags[boolTag] = cloneableTags[dateTag] =
+ cloneableTags[float32Tag] = cloneableTags[float64Tag] =
+ cloneableTags[int8Tag] = cloneableTags[int16Tag] =
+ cloneableTags[int32Tag] = cloneableTags[mapTag] =
+ cloneableTags[numberTag] = cloneableTags[objectTag] =
+ cloneableTags[regexpTag] = cloneableTags[setTag] =
+ cloneableTags[stringTag] = cloneableTags[symbolTag] =
+ cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
+ cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+ cloneableTags[errorTag] = cloneableTags[funcTag] =
+ cloneableTags[weakMapTag] = false;
+
+ /** Used to map Latin Unicode letters to basic Latin letters. */
+ var deburredLetters = {
+ // Latin-1 Supplement block.
+ '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
+ '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
+ '\xc7': 'C', '\xe7': 'c',
+ '\xd0': 'D', '\xf0': 'd',
+ '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
+ '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
+ '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
+ '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
+ '\xd1': 'N', '\xf1': 'n',
+ '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
+ '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
+ '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
+ '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
+ '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
+ '\xc6': 'Ae', '\xe6': 'ae',
+ '\xde': 'Th', '\xfe': 'th',
+ '\xdf': 'ss',
+ // Latin Extended-A block.
+ '\u0100': 'A', '\u0102': 'A', '\u0104': 'A',
+ '\u0101': 'a', '\u0103': 'a', '\u0105': 'a',
+ '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
+ '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
+ '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
+ '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
+ '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
+ '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
+ '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
+ '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
+ '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
+ '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
+ '\u0134': 'J', '\u0135': 'j',
+ '\u0136': 'K', '\u0137': 'k', '\u0138': 'k',
+ '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
+ '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
+ '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
+ '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
+ '\u014c': 'O', '\u014e': 'O', '\u0150': 'O',
+ '\u014d': 'o', '\u014f': 'o', '\u0151': 'o',
+ '\u0154': 'R', '\u0156': 'R', '\u0158': 'R',
+ '\u0155': 'r', '\u0157': 'r', '\u0159': 'r',
+ '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
+ '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's',
+ '\u0162': 'T', '\u0164': 'T', '\u0166': 'T',
+ '\u0163': 't', '\u0165': 't', '\u0167': 't',
+ '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
+ '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
+ '\u0174': 'W', '\u0175': 'w',
+ '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y',
+ '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z',
+ '\u017a': 'z', '\u017c': 'z', '\u017e': 'z',
+ '\u0132': 'IJ', '\u0133': 'ij',
+ '\u0152': 'Oe', '\u0153': 'oe',
+ '\u0149': "'n", '\u017f': 's'
+ };
+
+ /** Used to map characters to HTML entities. */
+ var htmlEscapes = {
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ "'": '&#39;'
+ };
+
+ /** Used to map HTML entities to characters. */
+ var htmlUnescapes = {
+ '&amp;': '&',
+ '&lt;': '<',
+ '&gt;': '>',
+ '&quot;': '"',
+ '&#39;': "'"
+ };
+
+ /** Used to escape characters for inclusion in compiled string literals. */
+ var stringEscapes = {
+ '\\': '\\',
+ "'": "'",
+ '\n': 'n',
+ '\r': 'r',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ /** Built-in method references without a dependency on `root`. */
+ var freeParseFloat = parseFloat,
+ freeParseInt = parseInt;
+
+ /** Detect free variable `global` from Node.js. */
+ var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
+
+ /** Detect free variable `self`. */
+ var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
+
+ /** Used as a reference to the global object. */
+ var root = freeGlobal || freeSelf || Function('return this')();
+
+ /** Detect free variable `exports`. */
+ var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
+
+ /** Detect free variable `module`. */
+ var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
+
+ /** Detect the popular CommonJS extension `module.exports`. */
+ var moduleExports = freeModule && freeModule.exports === freeExports;
+
+ /** Detect free variable `process` from Node.js. */
+ var freeProcess = moduleExports && freeGlobal.process;
+
+ /** Used to access faster Node.js helpers. */
+ var nodeUtil = (function() {
+ try {
+ return freeProcess && freeProcess.binding && freeProcess.binding('util');
+ } catch (e) {}
+ }());
+
+ /* Node.js helper references. */
+ var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
+ nodeIsDate = nodeUtil && nodeUtil.isDate,
+ nodeIsMap = nodeUtil && nodeUtil.isMap,
+ nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
+ nodeIsSet = nodeUtil && nodeUtil.isSet,
+ nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Adds the key-value `pair` to `map`.
+ *
+ * @private
+ * @param {Object} map The map to modify.
+ * @param {Array} pair The key-value pair to add.
+ * @returns {Object} Returns `map`.
+ */
+ function addMapEntry(map, pair) {
+ // Don't return `map.set` because it's not chainable in IE 11.
+ map.set(pair[0], pair[1]);
+ return map;
+ }
+
+ /**
+ * Adds `value` to `set`.
+ *
+ * @private
+ * @param {Object} set The set to modify.
+ * @param {*} value The value to add.
+ * @returns {Object} Returns `set`.
+ */
+ function addSetEntry(set, value) {
+ // Don't return `set.add` because it's not chainable in IE 11.
+ set.add(value);
+ return set;
+ }
+
+ /**
+ * A faster alternative to `Function#apply`, this function invokes `func`
+ * with the `this` binding of `thisArg` and the arguments of `args`.
+ *
+ * @private
+ * @param {Function} func The function to invoke.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} args The arguments to invoke `func` with.
+ * @returns {*} Returns the result of `func`.
+ */
+ function apply(func, thisArg, args) {
+ switch (args.length) {
+ case 0: return func.call(thisArg);
+ case 1: return func.call(thisArg, args[0]);
+ case 2: return func.call(thisArg, args[0], args[1]);
+ case 3: return func.call(thisArg, args[0], args[1], args[2]);
+ }
+ return func.apply(thisArg, args);
+ }
+
+ /**
+ * A specialized version of `baseAggregator` for arrays.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform keys.
+ * @param {Object} accumulator The initial aggregated object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function arrayAggregator(array, setter, iteratee, accumulator) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ var value = array[index];
+ setter(accumulator, value, iteratee(value), array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.forEach` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.forEachRight` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEachRight(array, iteratee) {
+ var length = array == null ? 0 : array.length;
+
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.every` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ */
+ function arrayEvery(array, predicate) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A specialized version of `_.filter` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function arrayFilter(array, predicate) {
+ var index = -1,
+ length = array == null ? 0 : array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[resIndex++] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.includes` for arrays without support for
+ * specifying an index to search from.
+ *
+ * @private
+ * @param {Array} [array] The array to inspect.
+ * @param {*} target The value to search for.
+ * @returns {boolean} Returns `true` if `target` is found, else `false`.
+ */
+ function arrayIncludes(array, value) {
+ var length = array == null ? 0 : array.length;
+ return !!length && baseIndexOf(array, value, 0) > -1;
+ }
+
+ /**
+ * This function is like `arrayIncludes` except that it accepts a comparator.
+ *
+ * @private
+ * @param {Array} [array] The array to inspect.
+ * @param {*} target The value to search for.
+ * @param {Function} comparator The comparator invoked per element.
+ * @returns {boolean} Returns `true` if `target` is found, else `false`.
+ */
+ function arrayIncludesWith(array, value, comparator) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (comparator(value, array[index])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A specialized version of `_.map` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array == null ? 0 : array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
+
+ /**
+ * Appends the elements of `values` to `array`.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to append.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayPush(array, values) {
+ var index = -1,
+ length = values.length,
+ offset = array.length;
+
+ while (++index < length) {
+ array[offset + index] = values[index];
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.reduce` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initAccum] Specify using the first element of `array` as
+ * the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduce(array, iteratee, accumulator, initAccum) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ if (initAccum && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.reduceRight` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initAccum] Specify using the last element of `array` as
+ * the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduceRight(array, iteratee, accumulator, initAccum) {
+ var length = array == null ? 0 : array.length;
+ if (initAccum && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.some` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function arraySome(array, predicate) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets the size of an ASCII `string`.
+ *
+ * @private
+ * @param {string} string The string inspect.
+ * @returns {number} Returns the string size.
+ */
+ var asciiSize = baseProperty('length');
+
+ /**
+ * Converts an ASCII `string` to an array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function asciiToArray(string) {
+ return string.split('');
+ }
+
+ /**
+ * Splits an ASCII `string` into an array of its words.
+ *
+ * @private
+ * @param {string} The string to inspect.
+ * @returns {Array} Returns the words of `string`.
+ */
+ function asciiWords(string) {
+ return string.match(reAsciiWord) || [];
+ }
+
+ /**
+ * The base implementation of methods like `_.findKey` and `_.findLastKey`,
+ * without support for iteratee shorthands, which iterates over `collection`
+ * using `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to inspect.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @returns {*} Returns the found element or its key, else `undefined`.
+ */
+ function baseFindKey(collection, predicate, eachFunc) {
+ var result;
+ eachFunc(collection, function(value, key, collection) {
+ if (predicate(value, key, collection)) {
+ result = key;
+ return false;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.findIndex` and `_.findLastIndex` without
+ * support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {number} fromIndex The index to search from.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseFindIndex(array, predicate, fromIndex, fromRight) {
+ var length = array.length,
+ index = fromIndex + (fromRight ? 1 : -1);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseIndexOf(array, value, fromIndex) {
+ return value === value
+ ? strictIndexOf(array, value, fromIndex)
+ : baseFindIndex(array, baseIsNaN, fromIndex);
+ }
+
+ /**
+ * This function is like `baseIndexOf` except that it accepts a comparator.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @param {Function} comparator The comparator invoked per element.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseIndexOfWith(array, value, fromIndex, comparator) {
+ var index = fromIndex - 1,
+ length = array.length;
+
+ while (++index < length) {
+ if (comparator(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * The base implementation of `_.isNaN` without support for number objects.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ */
+ function baseIsNaN(value) {
+ return value !== value;
+ }
+
+ /**
+ * The base implementation of `_.mean` and `_.meanBy` without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {number} Returns the mean.
+ */
+ function baseMean(array, iteratee) {
+ var length = array == null ? 0 : array.length;
+ return length ? (baseSum(array, iteratee) / length) : NAN;
+ }
+
+ /**
+ * The base implementation of `_.property` without support for deep paths.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @returns {Function} Returns the new accessor function.
+ */
+ function baseProperty(key) {
+ return function(object) {
+ return object == null ? undefined : object[key];
+ };
+ }
+
+ /**
+ * The base implementation of `_.propertyOf` without support for deep paths.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Function} Returns the new accessor function.
+ */
+ function basePropertyOf(object) {
+ return function(key) {
+ return object == null ? undefined : object[key];
+ };
+ }
+
+ /**
+ * The base implementation of `_.reduce` and `_.reduceRight`, without support
+ * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} accumulator The initial value.
+ * @param {boolean} initAccum Specify using the first or last element of
+ * `collection` as the initial value.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @returns {*} Returns the accumulated value.
+ */
+ function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
+ eachFunc(collection, function(value, index, collection) {
+ accumulator = initAccum
+ ? (initAccum = false, value)
+ : iteratee(accumulator, value, index, collection);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.sortBy` which uses `comparer` to define the
+ * sort order of `array` and replaces criteria objects with their corresponding
+ * values.
+ *
+ * @private
+ * @param {Array} array The array to sort.
+ * @param {Function} comparer The function to define sort order.
+ * @returns {Array} Returns `array`.
+ */
+ function baseSortBy(array, comparer) {
+ var length = array.length;
+
+ array.sort(comparer);
+ while (length--) {
+ array[length] = array[length].value;
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.sum` and `_.sumBy` without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {number} Returns the sum.
+ */
+ function baseSum(array, iteratee) {
+ var result,
+ index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var current = iteratee(array[index]);
+ if (current !== undefined) {
+ result = result === undefined ? current : (result + current);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.times` without support for iteratee shorthands
+ * or max array length checks.
+ *
+ * @private
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the array of results.
+ */
+ function baseTimes(n, iteratee) {
+ var index = -1,
+ result = Array(n);
+
+ while (++index < n) {
+ result[index] = iteratee(index);
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
+ * of key-value pairs for `object` corresponding to the property names of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the key-value pairs.
+ */
+ function baseToPairs(object, props) {
+ return arrayMap(props, function(key) {
+ return [key, object[key]];
+ });
+ }
+
+ /**
+ * The base implementation of `_.unary` without support for storing metadata.
+ *
+ * @private
+ * @param {Function} func The function to cap arguments for.
+ * @returns {Function} Returns the new capped function.
+ */
+ function baseUnary(func) {
+ return function(value) {
+ return func(value);
+ };
+ }
+
+ /**
+ * The base implementation of `_.values` and `_.valuesIn` which creates an
+ * array of `object` property values corresponding to the property names
+ * of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the array of property values.
+ */
+ function baseValues(object, props) {
+ return arrayMap(props, function(key) {
+ return object[key];
+ });
+ }
+
+ /**
+ * Checks if a `cache` value for `key` exists.
+ *
+ * @private
+ * @param {Object} cache The cache to query.
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function cacheHas(cache, key) {
+ return cache.has(key);
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
+ * that is not found in the character symbols.
+ *
+ * @private
+ * @param {Array} strSymbols The string symbols to inspect.
+ * @param {Array} chrSymbols The character symbols to find.
+ * @returns {number} Returns the index of the first unmatched string symbol.
+ */
+ function charsStartIndex(strSymbols, chrSymbols) {
+ var index = -1,
+ length = strSymbols.length;
+
+ while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
+ return index;
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
+ * that is not found in the character symbols.
+ *
+ * @private
+ * @param {Array} strSymbols The string symbols to inspect.
+ * @param {Array} chrSymbols The character symbols to find.
+ * @returns {number} Returns the index of the last unmatched string symbol.
+ */
+ function charsEndIndex(strSymbols, chrSymbols) {
+ var index = strSymbols.length;
+
+ while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
+ return index;
+ }
+
+ /**
+ * Gets the number of `placeholder` occurrences in `array`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} placeholder The placeholder to search for.
+ * @returns {number} Returns the placeholder count.
+ */
+ function countHolders(array, placeholder) {
+ var length = array.length,
+ result = 0;
+
+ while (length--) {
+ if (array[length] === placeholder) {
+ ++result;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
+ * letters to basic Latin letters.
+ *
+ * @private
+ * @param {string} letter The matched letter to deburr.
+ * @returns {string} Returns the deburred letter.
+ */
+ var deburrLetter = basePropertyOf(deburredLetters);
+
+ /**
+ * Used by `_.escape` to convert characters to HTML entities.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ var escapeHtmlChar = basePropertyOf(htmlEscapes);
+
+ /**
+ * Used by `_.template` to escape characters for inclusion in compiled string literals.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeStringChar(chr) {
+ return '\\' + stringEscapes[chr];
+ }
+
+ /**
+ * Gets the value at `key` of `object`.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {string} key The key of the property to get.
+ * @returns {*} Returns the property value.
+ */
+ function getValue(object, key) {
+ return object == null ? undefined : object[key];
+ }
+
+ /**
+ * Checks if `string` contains Unicode symbols.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {boolean} Returns `true` if a symbol is found, else `false`.
+ */
+ function hasUnicode(string) {
+ return reHasUnicode.test(string);
+ }
+
+ /**
+ * Checks if `string` contains a word composed of Unicode symbols.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {boolean} Returns `true` if a word is found, else `false`.
+ */
+ function hasUnicodeWord(string) {
+ return reHasUnicodeWord.test(string);
+ }
+
+ /**
+ * Converts `iterator` to an array.
+ *
+ * @private
+ * @param {Object} iterator The iterator to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function iteratorToArray(iterator) {
+ var data,
+ result = [];
+
+ while (!(data = iterator.next()).done) {
+ result.push(data.value);
+ }
+ return result;
+ }
+
+ /**
+ * Converts `map` to its key-value pairs.
+ *
+ * @private
+ * @param {Object} map The map to convert.
+ * @returns {Array} Returns the key-value pairs.
+ */
+ function mapToArray(map) {
+ var index = -1,
+ result = Array(map.size);
+
+ map.forEach(function(value, key) {
+ result[++index] = [key, value];
+ });
+ return result;
+ }
+
+ /**
+ * Creates a unary function that invokes `func` with its argument transformed.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {Function} transform The argument transform.
+ * @returns {Function} Returns the new function.
+ */
+ function overArg(func, transform) {
+ return function(arg) {
+ return func(transform(arg));
+ };
+ }
+
+ /**
+ * Replaces all `placeholder` elements in `array` with an internal placeholder
+ * and returns an array of their indexes.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {*} placeholder The placeholder to replace.
+ * @returns {Array} Returns the new array of placeholder indexes.
+ */
+ function replaceHolders(array, placeholder) {
+ var index = -1,
+ length = array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (value === placeholder || value === PLACEHOLDER) {
+ array[index] = PLACEHOLDER;
+ result[resIndex++] = index;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Converts `set` to an array of its values.
+ *
+ * @private
+ * @param {Object} set The set to convert.
+ * @returns {Array} Returns the values.
+ */
+ function setToArray(set) {
+ var index = -1,
+ result = Array(set.size);
+
+ set.forEach(function(value) {
+ result[++index] = value;
+ });
+ return result;
+ }
+
+ /**
+ * Converts `set` to its value-value pairs.
+ *
+ * @private
+ * @param {Object} set The set to convert.
+ * @returns {Array} Returns the value-value pairs.
+ */
+ function setToPairs(set) {
+ var index = -1,
+ result = Array(set.size);
+
+ set.forEach(function(value) {
+ result[++index] = [value, value];
+ });
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.indexOf` which performs strict equality
+ * comparisons of values, i.e. `===`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function strictIndexOf(array, value, fromIndex) {
+ var index = fromIndex - 1,
+ length = array.length;
+
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * A specialized version of `_.lastIndexOf` which performs strict equality
+ * comparisons of values, i.e. `===`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function strictLastIndexOf(array, value, fromIndex) {
+ var index = fromIndex + 1;
+ while (index--) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Gets the number of symbols in `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the string size.
+ */
+ function stringSize(string) {
+ return hasUnicode(string)
+ ? unicodeSize(string)
+ : asciiSize(string);
+ }
+
+ /**
+ * Converts `string` to an array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function stringToArray(string) {
+ return hasUnicode(string)
+ ? unicodeToArray(string)
+ : asciiToArray(string);
+ }
+
+ /**
+ * Used by `_.unescape` to convert HTML entities to characters.
+ *
+ * @private
+ * @param {string} chr The matched character to unescape.
+ * @returns {string} Returns the unescaped character.
+ */
+ var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
+
+ /**
+ * Gets the size of a Unicode `string`.
+ *
+ * @private
+ * @param {string} string The string inspect.
+ * @returns {number} Returns the string size.
+ */
+ function unicodeSize(string) {
+ var result = reUnicode.lastIndex = 0;
+ while (reUnicode.test(string)) {
+ ++result;
+ }
+ return result;
+ }
+
+ /**
+ * Converts a Unicode `string` to an array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function unicodeToArray(string) {
+ return string.match(reUnicode) || [];
+ }
+
+ /**
+ * Splits a Unicode `string` into an array of its words.
+ *
+ * @private
+ * @param {string} The string to inspect.
+ * @returns {Array} Returns the words of `string`.
+ */
+ function unicodeWords(string) {
+ return string.match(reUnicodeWord) || [];
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Create a new pristine `lodash` function using the `context` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category Util
+ * @param {Object} [context=root] The context object.
+ * @returns {Function} Returns a new `lodash` function.
+ * @example
+ *
+ * _.mixin({ 'foo': _.constant('foo') });
+ *
+ * var lodash = _.runInContext();
+ * lodash.mixin({ 'bar': lodash.constant('bar') });
+ *
+ * _.isFunction(_.foo);
+ * // => true
+ * _.isFunction(_.bar);
+ * // => false
+ *
+ * lodash.isFunction(lodash.foo);
+ * // => false
+ * lodash.isFunction(lodash.bar);
+ * // => true
+ *
+ * // Create a suped-up `defer` in Node.js.
+ * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
+ */
+ var runInContext = (function runInContext(context) {
+ context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
+
+ /** Built-in constructor references. */
+ var Array = context.Array,
+ Date = context.Date,
+ Error = context.Error,
+ Function = context.Function,
+ Math = context.Math,
+ Object = context.Object,
+ RegExp = context.RegExp,
+ String = context.String,
+ TypeError = context.TypeError;
+
+ /** Used for built-in method references. */
+ var arrayProto = Array.prototype,
+ funcProto = Function.prototype,
+ objectProto = Object.prototype;
+
+ /** Used to detect overreaching core-js shims. */
+ var coreJsData = context['__core-js_shared__'];
+
+ /** Used to resolve the decompiled source of functions. */
+ var funcToString = funcProto.toString;
+
+ /** Used to check objects for own properties. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
+
+ /** Used to generate unique IDs. */
+ var idCounter = 0;
+
+ /** Used to detect methods masquerading as native. */
+ var maskSrcKey = (function() {
+ var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
+ return uid ? ('Symbol(src)_1.' + uid) : '';
+ }());
+
+ /**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+ var nativeObjectToString = objectProto.toString;
+
+ /** Used to infer the `Object` constructor. */
+ var objectCtorString = funcToString.call(Object);
+
+ /** Used to restore the original `_` reference in `_.noConflict`. */
+ var oldDash = root._;
+
+ /** Used to detect if a method is native. */
+ var reIsNative = RegExp('^' +
+ funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+ );
+
+ /** Built-in value references. */
+ var Buffer = moduleExports ? context.Buffer : undefined,
+ Symbol = context.Symbol,
+ Uint8Array = context.Uint8Array,
+ allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,
+ getPrototype = overArg(Object.getPrototypeOf, Object),
+ objectCreate = Object.create,
+ propertyIsEnumerable = objectProto.propertyIsEnumerable,
+ splice = arrayProto.splice,
+ spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,
+ symIterator = Symbol ? Symbol.iterator : undefined,
+ symToStringTag = Symbol ? Symbol.toStringTag : undefined;
+
+ var defineProperty = (function() {
+ try {
+ var func = getNative(Object, 'defineProperty');
+ func({}, '', {});
+ return func;
+ } catch (e) {}
+ }());
+
+ /** Mocked built-ins. */
+ var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
+ ctxNow = Date && Date.now !== root.Date.now && Date.now,
+ ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
+
+ /* Built-in method references for those with the same name as other `lodash` methods. */
+ var nativeCeil = Math.ceil,
+ nativeFloor = Math.floor,
+ nativeGetSymbols = Object.getOwnPropertySymbols,
+ nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
+ nativeIsFinite = context.isFinite,
+ nativeJoin = arrayProto.join,
+ nativeKeys = overArg(Object.keys, Object),
+ nativeMax = Math.max,
+ nativeMin = Math.min,
+ nativeNow = Date.now,
+ nativeParseInt = context.parseInt,
+ nativeRandom = Math.random,
+ nativeReverse = arrayProto.reverse;
+
+ /* Built-in method references that are verified to be native. */
+ var DataView = getNative(context, 'DataView'),
+ Map = getNative(context, 'Map'),
+ Promise = getNative(context, 'Promise'),
+ Set = getNative(context, 'Set'),
+ WeakMap = getNative(context, 'WeakMap'),
+ nativeCreate = getNative(Object, 'create');
+
+ /** Used to store function metadata. */
+ var metaMap = WeakMap && new WeakMap;
+
+ /** Used to lookup unminified function names. */
+ var realNames = {};
+
+ /** Used to detect maps, sets, and weakmaps. */
+ var dataViewCtorString = toSource(DataView),
+ mapCtorString = toSource(Map),
+ promiseCtorString = toSource(Promise),
+ setCtorString = toSource(Set),
+ weakMapCtorString = toSource(WeakMap);
+
+ /** Used to convert symbols to primitives and strings. */
+ var symbolProto = Symbol ? Symbol.prototype : undefined,
+ symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
+ symbolToString = symbolProto ? symbolProto.toString : undefined;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a `lodash` object which wraps `value` to enable implicit method
+ * chain sequences. Methods that operate on and return arrays, collections,
+ * and functions can be chained together. Methods that retrieve a single value
+ * or may return a primitive value will automatically end the chain sequence
+ * and return the unwrapped value. Otherwise, the value must be unwrapped
+ * with `_#value`.
+ *
+ * Explicit chain sequences, which must be unwrapped with `_#value`, may be
+ * enabled using `_.chain`.
+ *
+ * The execution of chained methods is lazy, that is, it's deferred until
+ * `_#value` is implicitly or explicitly called.
+ *
+ * Lazy evaluation allows several methods to support shortcut fusion.
+ * Shortcut fusion is an optimization to merge iteratee calls; this avoids
+ * the creation of intermediate arrays and can greatly reduce the number of
+ * iteratee executions. Sections of a chain sequence qualify for shortcut
+ * fusion if the section is applied to an array and iteratees accept only
+ * one argument. The heuristic for whether a section qualifies for shortcut
+ * fusion is subject to change.
+ *
+ * Chaining is supported in custom builds as long as the `_#value` method is
+ * directly or indirectly included in the build.
+ *
+ * In addition to lodash methods, wrappers have `Array` and `String` methods.
+ *
+ * The wrapper `Array` methods are:
+ * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
+ *
+ * The wrapper `String` methods are:
+ * `replace` and `split`
+ *
+ * The wrapper methods that support shortcut fusion are:
+ * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
+ * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
+ * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
+ *
+ * The chainable wrapper methods are:
+ * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
+ * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
+ * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
+ * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
+ * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
+ * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
+ * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
+ * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
+ * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
+ * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
+ * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
+ * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
+ * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
+ * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
+ * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
+ * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
+ * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
+ * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
+ * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
+ * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
+ * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
+ * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
+ * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
+ * `zipObject`, `zipObjectDeep`, and `zipWith`
+ *
+ * The wrapper methods that are **not** chainable by default are:
+ * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
+ * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
+ * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
+ * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
+ * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
+ * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
+ * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
+ * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
+ * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
+ * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
+ * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
+ * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
+ * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
+ * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
+ * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
+ * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
+ * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
+ * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
+ * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
+ * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
+ * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
+ * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
+ * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
+ * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
+ * `upperFirst`, `value`, and `words`
+ *
+ * @name _
+ * @constructor
+ * @category Seq
+ * @param {*} value The value to wrap in a `lodash` instance.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var wrapped = _([1, 2, 3]);
+ *
+ * // Returns an unwrapped value.
+ * wrapped.reduce(_.add);
+ * // => 6
+ *
+ * // Returns a wrapped value.
+ * var squares = wrapped.map(square);
+ *
+ * _.isArray(squares);
+ * // => false
+ *
+ * _.isArray(squares.value());
+ * // => true
+ */
+ function lodash(value) {
+ if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
+ if (value instanceof LodashWrapper) {
+ return value;
+ }
+ if (hasOwnProperty.call(value, '__wrapped__')) {
+ return wrapperClone(value);
+ }
+ }
+ return new LodashWrapper(value);
+ }
+
+ /**
+ * The base implementation of `_.create` without support for assigning
+ * properties to the created object.
+ *
+ * @private
+ * @param {Object} proto The object to inherit from.
+ * @returns {Object} Returns the new object.
+ */
+ var baseCreate = (function() {
+ function object() {}
+ return function(proto) {
+ if (!isObject(proto)) {
+ return {};
+ }
+ if (objectCreate) {
+ return objectCreate(proto);
+ }
+ object.prototype = proto;
+ var result = new object;
+ object.prototype = undefined;
+ return result;
+ };
+ }());
+
+ /**
+ * The function whose prototype chain sequence wrappers inherit from.
+ *
+ * @private
+ */
+ function baseLodash() {
+ // No operation performed.
+ }
+
+ /**
+ * The base constructor for creating `lodash` wrapper objects.
+ *
+ * @private
+ * @param {*} value The value to wrap.
+ * @param {boolean} [chainAll] Enable explicit method chain sequences.
+ */
+ function LodashWrapper(value, chainAll) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__chain__ = !!chainAll;
+ this.__index__ = 0;
+ this.__values__ = undefined;
+ }
+
+ /**
+ * By default, the template delimiters used by lodash are like those in
+ * embedded Ruby (ERB) as well as ES2015 template strings. Change the
+ * following template settings to use alternative delimiters.
+ *
+ * @static
+ * @memberOf _
+ * @type {Object}
+ */
+ lodash.templateSettings = {
+
+ /**
+ * Used to detect `data` property values to be HTML-escaped.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'escape': reEscape,
+
+ /**
+ * Used to detect code to be evaluated.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'evaluate': reEvaluate,
+
+ /**
+ * Used to detect `data` property values to inject.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'interpolate': reInterpolate,
+
+ /**
+ * Used to reference the data object in the template text.
+ *
+ * @memberOf _.templateSettings
+ * @type {string}
+ */
+ 'variable': '',
+
+ /**
+ * Used to import variables into the compiled template.
+ *
+ * @memberOf _.templateSettings
+ * @type {Object}
+ */
+ 'imports': {
+
+ /**
+ * A reference to the `lodash` function.
+ *
+ * @memberOf _.templateSettings.imports
+ * @type {Function}
+ */
+ '_': lodash
+ }
+ };
+
+ // Ensure wrappers are instances of `baseLodash`.
+ lodash.prototype = baseLodash.prototype;
+ lodash.prototype.constructor = lodash;
+
+ LodashWrapper.prototype = baseCreate(baseLodash.prototype);
+ LodashWrapper.prototype.constructor = LodashWrapper;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
+ *
+ * @private
+ * @constructor
+ * @param {*} value The value to wrap.
+ */
+ function LazyWrapper(value) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__dir__ = 1;
+ this.__filtered__ = false;
+ this.__iteratees__ = [];
+ this.__takeCount__ = MAX_ARRAY_LENGTH;
+ this.__views__ = [];
+ }
+
+ /**
+ * Creates a clone of the lazy wrapper object.
+ *
+ * @private
+ * @name clone
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the cloned `LazyWrapper` object.
+ */
+ function lazyClone() {
+ var result = new LazyWrapper(this.__wrapped__);
+ result.__actions__ = copyArray(this.__actions__);
+ result.__dir__ = this.__dir__;
+ result.__filtered__ = this.__filtered__;
+ result.__iteratees__ = copyArray(this.__iteratees__);
+ result.__takeCount__ = this.__takeCount__;
+ result.__views__ = copyArray(this.__views__);
+ return result;
+ }
+
+ /**
+ * Reverses the direction of lazy iteration.
+ *
+ * @private
+ * @name reverse
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the new reversed `LazyWrapper` object.
+ */
+ function lazyReverse() {
+ if (this.__filtered__) {
+ var result = new LazyWrapper(this);
+ result.__dir__ = -1;
+ result.__filtered__ = true;
+ } else {
+ result = this.clone();
+ result.__dir__ *= -1;
+ }
+ return result;
+ }
+
+ /**
+ * Extracts the unwrapped value from its lazy wrapper.
+ *
+ * @private
+ * @name value
+ * @memberOf LazyWrapper
+ * @returns {*} Returns the unwrapped value.
+ */
+ function lazyValue() {
+ var array = this.__wrapped__.value(),
+ dir = this.__dir__,
+ isArr = isArray(array),
+ isRight = dir < 0,
+ arrLength = isArr ? array.length : 0,
+ view = getView(0, arrLength, this.__views__),
+ start = view.start,
+ end = view.end,
+ length = end - start,
+ index = isRight ? end : (start - 1),
+ iteratees = this.__iteratees__,
+ iterLength = iteratees.length,
+ resIndex = 0,
+ takeCount = nativeMin(length, this.__takeCount__);
+
+ if (!isArr || (!isRight && arrLength == length && takeCount == length)) {
+ return baseWrapperValue(array, this.__actions__);
+ }
+ var result = [];
+
+ outer:
+ while (length-- && resIndex < takeCount) {
+ index += dir;
+
+ var iterIndex = -1,
+ value = array[index];
+
+ while (++iterIndex < iterLength) {
+ var data = iteratees[iterIndex],
+ iteratee = data.iteratee,
+ type = data.type,
+ computed = iteratee(value);
+
+ if (type == LAZY_MAP_FLAG) {
+ value = computed;
+ } else if (!computed) {
+ if (type == LAZY_FILTER_FLAG) {
+ continue outer;
+ } else {
+ break outer;
+ }
+ }
+ }
+ result[resIndex++] = value;
+ }
+ return result;
+ }
+
+ // Ensure `LazyWrapper` is an instance of `baseLodash`.
+ LazyWrapper.prototype = baseCreate(baseLodash.prototype);
+ LazyWrapper.prototype.constructor = LazyWrapper;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a hash object.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+ function Hash(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+
+ /**
+ * Removes all key-value entries from the hash.
+ *
+ * @private
+ * @name clear
+ * @memberOf Hash
+ */
+ function hashClear() {
+ this.__data__ = nativeCreate ? nativeCreate(null) : {};
+ this.size = 0;
+ }
+
+ /**
+ * Removes `key` and its value from the hash.
+ *
+ * @private
+ * @name delete
+ * @memberOf Hash
+ * @param {Object} hash The hash to modify.
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function hashDelete(key) {
+ var result = this.has(key) && delete this.__data__[key];
+ this.size -= result ? 1 : 0;
+ return result;
+ }
+
+ /**
+ * Gets the hash value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Hash
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function hashGet(key) {
+ var data = this.__data__;
+ if (nativeCreate) {
+ var result = data[key];
+ return result === HASH_UNDEFINED ? undefined : result;
+ }
+ return hasOwnProperty.call(data, key) ? data[key] : undefined;
+ }
+
+ /**
+ * Checks if a hash value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Hash
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function hashHas(key) {
+ var data = this.__data__;
+ return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
+ }
+
+ /**
+ * Sets the hash `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Hash
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the hash instance.
+ */
+ function hashSet(key, value) {
+ var data = this.__data__;
+ this.size += this.has(key) ? 0 : 1;
+ data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
+ return this;
+ }
+
+ // Add methods to `Hash`.
+ Hash.prototype.clear = hashClear;
+ Hash.prototype['delete'] = hashDelete;
+ Hash.prototype.get = hashGet;
+ Hash.prototype.has = hashHas;
+ Hash.prototype.set = hashSet;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an list cache object.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+ function ListCache(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+
+ /**
+ * Removes all key-value entries from the list cache.
+ *
+ * @private
+ * @name clear
+ * @memberOf ListCache
+ */
+ function listCacheClear() {
+ this.__data__ = [];
+ this.size = 0;
+ }
+
+ /**
+ * Removes `key` and its value from the list cache.
+ *
+ * @private
+ * @name delete
+ * @memberOf ListCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function listCacheDelete(key) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ if (index < 0) {
+ return false;
+ }
+ var lastIndex = data.length - 1;
+ if (index == lastIndex) {
+ data.pop();
+ } else {
+ splice.call(data, index, 1);
+ }
+ --this.size;
+ return true;
+ }
+
+ /**
+ * Gets the list cache value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf ListCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function listCacheGet(key) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ return index < 0 ? undefined : data[index][1];
+ }
+
+ /**
+ * Checks if a list cache value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf ListCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function listCacheHas(key) {
+ return assocIndexOf(this.__data__, key) > -1;
+ }
+
+ /**
+ * Sets the list cache `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf ListCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the list cache instance.
+ */
+ function listCacheSet(key, value) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ if (index < 0) {
+ ++this.size;
+ data.push([key, value]);
+ } else {
+ data[index][1] = value;
+ }
+ return this;
+ }
+
+ // Add methods to `ListCache`.
+ ListCache.prototype.clear = listCacheClear;
+ ListCache.prototype['delete'] = listCacheDelete;
+ ListCache.prototype.get = listCacheGet;
+ ListCache.prototype.has = listCacheHas;
+ ListCache.prototype.set = listCacheSet;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a map cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+ function MapCache(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+
+ /**
+ * Removes all key-value entries from the map.
+ *
+ * @private
+ * @name clear
+ * @memberOf MapCache
+ */
+ function mapCacheClear() {
+ this.size = 0;
+ this.__data__ = {
+ 'hash': new Hash,
+ 'map': new (Map || ListCache),
+ 'string': new Hash
+ };
+ }
+
+ /**
+ * Removes `key` and its value from the map.
+ *
+ * @private
+ * @name delete
+ * @memberOf MapCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function mapCacheDelete(key) {
+ var result = getMapData(this, key)['delete'](key);
+ this.size -= result ? 1 : 0;
+ return result;
+ }
+
+ /**
+ * Gets the map value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf MapCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function mapCacheGet(key) {
+ return getMapData(this, key).get(key);
+ }
+
+ /**
+ * Checks if a map value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf MapCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function mapCacheHas(key) {
+ return getMapData(this, key).has(key);
+ }
+
+ /**
+ * Sets the map `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf MapCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the map cache instance.
+ */
+ function mapCacheSet(key, value) {
+ var data = getMapData(this, key),
+ size = data.size;
+
+ data.set(key, value);
+ this.size += data.size == size ? 0 : 1;
+ return this;
+ }
+
+ // Add methods to `MapCache`.
+ MapCache.prototype.clear = mapCacheClear;
+ MapCache.prototype['delete'] = mapCacheDelete;
+ MapCache.prototype.get = mapCacheGet;
+ MapCache.prototype.has = mapCacheHas;
+ MapCache.prototype.set = mapCacheSet;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ *
+ * Creates an array cache object to store unique values.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [values] The values to cache.
+ */
+ function SetCache(values) {
+ var index = -1,
+ length = values == null ? 0 : values.length;
+
+ this.__data__ = new MapCache;
+ while (++index < length) {
+ this.add(values[index]);
+ }
+ }
+
+ /**
+ * Adds `value` to the array cache.
+ *
+ * @private
+ * @name add
+ * @memberOf SetCache
+ * @alias push
+ * @param {*} value The value to cache.
+ * @returns {Object} Returns the cache instance.
+ */
+ function setCacheAdd(value) {
+ this.__data__.set(value, HASH_UNDEFINED);
+ return this;
+ }
+
+ /**
+ * Checks if `value` is in the array cache.
+ *
+ * @private
+ * @name has
+ * @memberOf SetCache
+ * @param {*} value The value to search for.
+ * @returns {number} Returns `true` if `value` is found, else `false`.
+ */
+ function setCacheHas(value) {
+ return this.__data__.has(value);
+ }
+
+ // Add methods to `SetCache`.
+ SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
+ SetCache.prototype.has = setCacheHas;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a stack cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+ function Stack(entries) {
+ var data = this.__data__ = new ListCache(entries);
+ this.size = data.size;
+ }
+
+ /**
+ * Removes all key-value entries from the stack.
+ *
+ * @private
+ * @name clear
+ * @memberOf Stack
+ */
+ function stackClear() {
+ this.__data__ = new ListCache;
+ this.size = 0;
+ }
+
+ /**
+ * Removes `key` and its value from the stack.
+ *
+ * @private
+ * @name delete
+ * @memberOf Stack
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function stackDelete(key) {
+ var data = this.__data__,
+ result = data['delete'](key);
+
+ this.size = data.size;
+ return result;
+ }
+
+ /**
+ * Gets the stack value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Stack
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function stackGet(key) {
+ return this.__data__.get(key);
+ }
+
+ /**
+ * Checks if a stack value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Stack
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function stackHas(key) {
+ return this.__data__.has(key);
+ }
+
+ /**
+ * Sets the stack `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Stack
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the stack cache instance.
+ */
+ function stackSet(key, value) {
+ var data = this.__data__;
+ if (data instanceof ListCache) {
+ var pairs = data.__data__;
+ if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
+ pairs.push([key, value]);
+ this.size = ++data.size;
+ return this;
+ }
+ data = this.__data__ = new MapCache(pairs);
+ }
+ data.set(key, value);
+ this.size = data.size;
+ return this;
+ }
+
+ // Add methods to `Stack`.
+ Stack.prototype.clear = stackClear;
+ Stack.prototype['delete'] = stackDelete;
+ Stack.prototype.get = stackGet;
+ Stack.prototype.has = stackHas;
+ Stack.prototype.set = stackSet;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an array of the enumerable property names of the array-like `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @param {boolean} inherited Specify returning inherited property names.
+ * @returns {Array} Returns the array of property names.
+ */
+ function arrayLikeKeys(value, inherited) {
+ var isArr = isArray(value),
+ isArg = !isArr && isArguments(value),
+ isBuff = !isArr && !isArg && isBuffer(value),
+ isType = !isArr && !isArg && !isBuff && isTypedArray(value),
+ skipIndexes = isArr || isArg || isBuff || isType,
+ result = skipIndexes ? baseTimes(value.length, String) : [],
+ length = result.length;
+
+ for (var key in value) {
+ if ((inherited || hasOwnProperty.call(value, key)) &&
+ !(skipIndexes && (
+ // Safari 9 has enumerable `arguments.length` in strict mode.
+ key == 'length' ||
+ // Node.js 0.10 has enumerable non-index properties on buffers.
+ (isBuff && (key == 'offset' || key == 'parent')) ||
+ // PhantomJS 2 has enumerable non-index properties on typed arrays.
+ (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
+ // Skip index properties.
+ isIndex(key, length)
+ ))) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.sample` for arrays.
+ *
+ * @private
+ * @param {Array} array The array to sample.
+ * @returns {*} Returns the random element.
+ */
+ function arraySample(array) {
+ var length = array.length;
+ return length ? array[baseRandom(0, length - 1)] : undefined;
+ }
+
+ /**
+ * A specialized version of `_.sampleSize` for arrays.
+ *
+ * @private
+ * @param {Array} array The array to sample.
+ * @param {number} n The number of elements to sample.
+ * @returns {Array} Returns the random elements.
+ */
+ function arraySampleSize(array, n) {
+ return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
+ }
+
+ /**
+ * A specialized version of `_.shuffle` for arrays.
+ *
+ * @private
+ * @param {Array} array The array to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ */
+ function arrayShuffle(array) {
+ return shuffleSelf(copyArray(array));
+ }
+
+ /**
+ * This function is like `assignValue` except that it doesn't assign
+ * `undefined` values.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+ function assignMergeValue(object, key, value) {
+ if ((value !== undefined && !eq(object[key], value)) ||
+ (value === undefined && !(key in object))) {
+ baseAssignValue(object, key, value);
+ }
+ }
+
+ /**
+ * Assigns `value` to `key` of `object` if the existing value is not equivalent
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+ function assignValue(object, key, value) {
+ var objValue = object[key];
+ if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
+ (value === undefined && !(key in object))) {
+ baseAssignValue(object, key, value);
+ }
+ }
+
+ /**
+ * Gets the index at which the `key` is found in `array` of key-value pairs.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} key The key to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function assocIndexOf(array, key) {
+ var length = array.length;
+ while (length--) {
+ if (eq(array[length][0], key)) {
+ return length;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Aggregates elements of `collection` on `accumulator` with keys transformed
+ * by `iteratee` and values set by `setter`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform keys.
+ * @param {Object} accumulator The initial aggregated object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function baseAggregator(collection, setter, iteratee, accumulator) {
+ baseEach(collection, function(value, key, collection) {
+ setter(accumulator, value, iteratee(value), collection);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.assign` without support for multiple sources
+ * or `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+ function baseAssign(object, source) {
+ return object && copyObject(source, keys(source), object);
+ }
+
+ /**
+ * The base implementation of `_.assignIn` without support for multiple sources
+ * or `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+ function baseAssignIn(object, source) {
+ return object && copyObject(source, keysIn(source), object);
+ }
+
+ /**
+ * The base implementation of `assignValue` and `assignMergeValue` without
+ * value checks.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+ function baseAssignValue(object, key, value) {
+ if (key == '__proto__' && defineProperty) {
+ defineProperty(object, key, {
+ 'configurable': true,
+ 'enumerable': true,
+ 'value': value,
+ 'writable': true
+ });
+ } else {
+ object[key] = value;
+ }
+ }
+
+ /**
+ * The base implementation of `_.at` without support for individual paths.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {string[]} paths The property paths to pick.
+ * @returns {Array} Returns the picked elements.
+ */
+ function baseAt(object, paths) {
+ var index = -1,
+ length = paths.length,
+ result = Array(length),
+ skip = object == null;
+
+ while (++index < length) {
+ result[index] = skip ? undefined : get(object, paths[index]);
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.clamp` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {number} number The number to clamp.
+ * @param {number} [lower] The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the clamped number.
+ */
+ function baseClamp(number, lower, upper) {
+ if (number === number) {
+ if (upper !== undefined) {
+ number = number <= upper ? number : upper;
+ }
+ if (lower !== undefined) {
+ number = number >= lower ? number : lower;
+ }
+ }
+ return number;
+ }
+
+ /**
+ * The base implementation of `_.clone` and `_.cloneDeep` which tracks
+ * traversed objects.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @param {boolean} bitmask The bitmask flags.
+ * 1 - Deep clone
+ * 2 - Flatten inherited properties
+ * 4 - Clone symbols
+ * @param {Function} [customizer] The function to customize cloning.
+ * @param {string} [key] The key of `value`.
+ * @param {Object} [object] The parent object of `value`.
+ * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
+ * @returns {*} Returns the cloned value.
+ */
+ function baseClone(value, bitmask, customizer, key, object, stack) {
+ var result,
+ isDeep = bitmask & CLONE_DEEP_FLAG,
+ isFlat = bitmask & CLONE_FLAT_FLAG,
+ isFull = bitmask & CLONE_SYMBOLS_FLAG;
+
+ if (customizer) {
+ result = object ? customizer(value, key, object, stack) : customizer(value);
+ }
+ if (result !== undefined) {
+ return result;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result = initCloneArray(value);
+ if (!isDeep) {
+ return copyArray(value, result);
+ }
+ } else {
+ var tag = getTag(value),
+ isFunc = tag == funcTag || tag == genTag;
+
+ if (isBuffer(value)) {
+ return cloneBuffer(value, isDeep);
+ }
+ if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
+ result = (isFlat || isFunc) ? {} : initCloneObject(value);
+ if (!isDeep) {
+ return isFlat
+ ? copySymbolsIn(value, baseAssignIn(result, value))
+ : copySymbols(value, baseAssign(result, value));
+ }
+ } else {
+ if (!cloneableTags[tag]) {
+ return object ? value : {};
+ }
+ result = initCloneByTag(value, tag, baseClone, isDeep);
+ }
+ }
+ // Check for circular references and return its corresponding clone.
+ stack || (stack = new Stack);
+ var stacked = stack.get(value);
+ if (stacked) {
+ return stacked;
+ }
+ stack.set(value, result);
+
+ var keysFunc = isFull
+ ? (isFlat ? getAllKeysIn : getAllKeys)
+ : (isFlat ? keysIn : keys);
+
+ var props = isArr ? undefined : keysFunc(value);
+ arrayEach(props || value, function(subValue, key) {
+ if (props) {
+ key = subValue;
+ subValue = value[key];
+ }
+ // Recursively populate clone (susceptible to call stack limits).
+ assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.conforms` which doesn't clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {Function} Returns the new spec function.
+ */
+ function baseConforms(source) {
+ var props = keys(source);
+ return function(object) {
+ return baseConformsTo(object, source, props);
+ };
+ }
+
+ /**
+ * The base implementation of `_.conformsTo` which accepts `props` to check.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {boolean} Returns `true` if `object` conforms, else `false`.
+ */
+ function baseConformsTo(object, source, props) {
+ var length = props.length;
+ if (object == null) {
+ return !length;
+ }
+ object = Object(object);
+ while (length--) {
+ var key = props[length],
+ predicate = source[key],
+ value = object[key];
+
+ if ((value === undefined && !(key in object)) || !predicate(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * The base implementation of `_.delay` and `_.defer` which accepts `args`
+ * to provide to `func`.
+ *
+ * @private
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {Array} args The arguments to provide to `func`.
+ * @returns {number|Object} Returns the timer id or timeout object.
+ */
+ function baseDelay(func, wait, args) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return setTimeout(function() { func.apply(undefined, args); }, wait);
+ }
+
+ /**
+ * The base implementation of methods like `_.difference` without support
+ * for excluding multiple arrays or iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Array} values The values to exclude.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ */
+ function baseDifference(array, values, iteratee, comparator) {
+ var index = -1,
+ includes = arrayIncludes,
+ isCommon = true,
+ length = array.length,
+ result = [],
+ valuesLength = values.length;
+
+ if (!length) {
+ return result;
+ }
+ if (iteratee) {
+ values = arrayMap(values, baseUnary(iteratee));
+ }
+ if (comparator) {
+ includes = arrayIncludesWith;
+ isCommon = false;
+ }
+ else if (values.length >= LARGE_ARRAY_SIZE) {
+ includes = cacheHas;
+ isCommon = false;
+ values = new SetCache(values);
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee == null ? value : iteratee(value);
+
+ value = (comparator || value !== 0) ? value : 0;
+ if (isCommon && computed === computed) {
+ var valuesIndex = valuesLength;
+ while (valuesIndex--) {
+ if (values[valuesIndex] === computed) {
+ continue outer;
+ }
+ }
+ result.push(value);
+ }
+ else if (!includes(values, computed, comparator)) {
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.forEach` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ */
+ var baseEach = createBaseEach(baseForOwn);
+
+ /**
+ * The base implementation of `_.forEachRight` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ */
+ var baseEachRight = createBaseEach(baseForOwnRight, true);
+
+ /**
+ * The base implementation of `_.every` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`
+ */
+ function baseEvery(collection, predicate) {
+ var result = true;
+ baseEach(collection, function(value, index, collection) {
+ result = !!predicate(value, index, collection);
+ return result;
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of methods like `_.max` and `_.min` which accepts a
+ * `comparator` to determine the extremum value.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The iteratee invoked per iteration.
+ * @param {Function} comparator The comparator used to compare values.
+ * @returns {*} Returns the extremum value.
+ */
+ function baseExtremum(array, iteratee, comparator) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var value = array[index],
+ current = iteratee(value);
+
+ if (current != null && (computed === undefined
+ ? (current === current && !isSymbol(current))
+ : comparator(current, computed)
+ )) {
+ var computed = current,
+ result = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.fill` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ */
+ function baseFill(array, value, start, end) {
+ var length = array.length;
+
+ start = toInteger(start);
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = (end === undefined || end > length) ? length : toInteger(end);
+ if (end < 0) {
+ end += length;
+ }
+ end = start > end ? 0 : toLength(end);
+ while (start < end) {
+ array[start++] = value;
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.filter` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function baseFilter(collection, predicate) {
+ var result = [];
+ baseEach(collection, function(value, index, collection) {
+ if (predicate(value, index, collection)) {
+ result.push(value);
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.flatten` with support for restricting flattening.
+ *
+ * @private
+ * @param {Array} array The array to flatten.
+ * @param {number} depth The maximum recursion depth.
+ * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
+ * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
+ * @param {Array} [result=[]] The initial result value.
+ * @returns {Array} Returns the new flattened array.
+ */
+ function baseFlatten(array, depth, predicate, isStrict, result) {
+ var index = -1,
+ length = array.length;
+
+ predicate || (predicate = isFlattenable);
+ result || (result = []);
+
+ while (++index < length) {
+ var value = array[index];
+ if (depth > 0 && predicate(value)) {
+ if (depth > 1) {
+ // Recursively flatten arrays (susceptible to call stack limits).
+ baseFlatten(value, depth - 1, predicate, isStrict, result);
+ } else {
+ arrayPush(result, value);
+ }
+ } else if (!isStrict) {
+ result[result.length] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `baseForOwn` which iterates over `object`
+ * properties returned by `keysFunc` and invokes `iteratee` for each property.
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+ var baseFor = createBaseFor();
+
+ /**
+ * This function is like `baseFor` except that it iterates over properties
+ * in the opposite order.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+ var baseForRight = createBaseFor(true);
+
+ /**
+ * The base implementation of `_.forOwn` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForOwn(object, iteratee) {
+ return object && baseFor(object, iteratee, keys);
+ }
+
+ /**
+ * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForOwnRight(object, iteratee) {
+ return object && baseForRight(object, iteratee, keys);
+ }
+
+ /**
+ * The base implementation of `_.functions` which creates an array of
+ * `object` function property names filtered from `props`.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Array} props The property names to filter.
+ * @returns {Array} Returns the function names.
+ */
+ function baseFunctions(object, props) {
+ return arrayFilter(props, function(key) {
+ return isFunction(object[key]);
+ });
+ }
+
+ /**
+ * The base implementation of `_.get` without support for default values.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseGet(object, path) {
+ path = castPath(path, object);
+
+ var index = 0,
+ length = path.length;
+
+ while (object != null && index < length) {
+ object = object[toKey(path[index++])];
+ }
+ return (index && index == length) ? object : undefined;
+ }
+
+ /**
+ * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
+ * `keysFunc` and `symbolsFunc` to get the enumerable property names and
+ * symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @param {Function} symbolsFunc The function to get the symbols of `object`.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+ function baseGetAllKeys(object, keysFunc, symbolsFunc) {
+ var result = keysFunc(object);
+ return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
+ }
+
+ /**
+ * The base implementation of `getTag` without fallbacks for buggy environments.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+ function baseGetTag(value) {
+ if (value == null) {
+ return value === undefined ? undefinedTag : nullTag;
+ }
+ return (symToStringTag && symToStringTag in Object(value))
+ ? getRawTag(value)
+ : objectToString(value);
+ }
+
+ /**
+ * The base implementation of `_.gt` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than `other`,
+ * else `false`.
+ */
+ function baseGt(value, other) {
+ return value > other;
+ }
+
+ /**
+ * The base implementation of `_.has` without support for deep paths.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {Array|string} key The key to check.
+ * @returns {boolean} Returns `true` if `key` exists, else `false`.
+ */
+ function baseHas(object, key) {
+ return object != null && hasOwnProperty.call(object, key);
+ }
+
+ /**
+ * The base implementation of `_.hasIn` without support for deep paths.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {Array|string} key The key to check.
+ * @returns {boolean} Returns `true` if `key` exists, else `false`.
+ */
+ function baseHasIn(object, key) {
+ return object != null && key in Object(object);
+ }
+
+ /**
+ * The base implementation of `_.inRange` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {number} number The number to check.
+ * @param {number} start The start of the range.
+ * @param {number} end The end of the range.
+ * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
+ */
+ function baseInRange(number, start, end) {
+ return number >= nativeMin(start, end) && number < nativeMax(start, end);
+ }
+
+ /**
+ * The base implementation of methods like `_.intersection`, without support
+ * for iteratee shorthands, that accepts an array of arrays to inspect.
+ *
+ * @private
+ * @param {Array} arrays The arrays to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of shared values.
+ */
+ function baseIntersection(arrays, iteratee, comparator) {
+ var includes = comparator ? arrayIncludesWith : arrayIncludes,
+ length = arrays[0].length,
+ othLength = arrays.length,
+ othIndex = othLength,
+ caches = Array(othLength),
+ maxLength = Infinity,
+ result = [];
+
+ while (othIndex--) {
+ var array = arrays[othIndex];
+ if (othIndex && iteratee) {
+ array = arrayMap(array, baseUnary(iteratee));
+ }
+ maxLength = nativeMin(array.length, maxLength);
+ caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
+ ? new SetCache(othIndex && array)
+ : undefined;
+ }
+ array = arrays[0];
+
+ var index = -1,
+ seen = caches[0];
+
+ outer:
+ while (++index < length && result.length < maxLength) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ value = (comparator || value !== 0) ? value : 0;
+ if (!(seen
+ ? cacheHas(seen, computed)
+ : includes(result, computed, comparator)
+ )) {
+ othIndex = othLength;
+ while (--othIndex) {
+ var cache = caches[othIndex];
+ if (!(cache
+ ? cacheHas(cache, computed)
+ : includes(arrays[othIndex], computed, comparator))
+ ) {
+ continue outer;
+ }
+ }
+ if (seen) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.invert` and `_.invertBy` which inverts
+ * `object` with values transformed by `iteratee` and set by `setter`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform values.
+ * @param {Object} accumulator The initial inverted object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function baseInverter(object, setter, iteratee, accumulator) {
+ baseForOwn(object, function(value, key, object) {
+ setter(accumulator, iteratee(value), key, object);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.invoke` without support for individual
+ * method arguments.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {Array} args The arguments to invoke the method with.
+ * @returns {*} Returns the result of the invoked method.
+ */
+ function baseInvoke(object, path, args) {
+ path = castPath(path, object);
+ object = parent(object, path);
+ var func = object == null ? object : object[toKey(last(path))];
+ return func == null ? undefined : apply(func, object, args);
+ }
+
+ /**
+ * The base implementation of `_.isArguments`.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
+ */
+ function baseIsArguments(value) {
+ return isObjectLike(value) && baseGetTag(value) == argsTag;
+ }
+
+ /**
+ * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
+ */
+ function baseIsArrayBuffer(value) {
+ return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
+ }
+
+ /**
+ * The base implementation of `_.isDate` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
+ */
+ function baseIsDate(value) {
+ return isObjectLike(value) && baseGetTag(value) == dateTag;
+ }
+
+ /**
+ * The base implementation of `_.isEqual` which supports partial comparisons
+ * and tracks traversed objects.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {boolean} bitmask The bitmask flags.
+ * 1 - Unordered comparison
+ * 2 - Partial comparison
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @param {Object} [stack] Tracks traversed `value` and `other` objects.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ */
+ function baseIsEqual(value, other, bitmask, customizer, stack) {
+ if (value === other) {
+ return true;
+ }
+ if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
+ return value !== value && other !== other;
+ }
+ return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
+ }
+
+ /**
+ * A specialized version of `baseIsEqual` for arrays and objects which performs
+ * deep comparisons and tracks traversed objects enabling objects with circular
+ * references to be compared.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} [stack] Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
+ var objIsArr = isArray(object),
+ othIsArr = isArray(other),
+ objTag = objIsArr ? arrayTag : getTag(object),
+ othTag = othIsArr ? arrayTag : getTag(other);
+
+ objTag = objTag == argsTag ? objectTag : objTag;
+ othTag = othTag == argsTag ? objectTag : othTag;
+
+ var objIsObj = objTag == objectTag,
+ othIsObj = othTag == objectTag,
+ isSameTag = objTag == othTag;
+
+ if (isSameTag && isBuffer(object)) {
+ if (!isBuffer(other)) {
+ return false;
+ }
+ objIsArr = true;
+ objIsObj = false;
+ }
+ if (isSameTag && !objIsObj) {
+ stack || (stack = new Stack);
+ return (objIsArr || isTypedArray(object))
+ ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
+ : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
+ }
+ if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
+ var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
+ othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
+
+ if (objIsWrapped || othIsWrapped) {
+ var objUnwrapped = objIsWrapped ? object.value() : object,
+ othUnwrapped = othIsWrapped ? other.value() : other;
+
+ stack || (stack = new Stack);
+ return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
+ }
+ }
+ if (!isSameTag) {
+ return false;
+ }
+ stack || (stack = new Stack);
+ return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
+ }
+
+ /**
+ * The base implementation of `_.isMap` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a map, else `false`.
+ */
+ function baseIsMap(value) {
+ return isObjectLike(value) && getTag(value) == mapTag;
+ }
+
+ /**
+ * The base implementation of `_.isMatch` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Array} matchData The property names, values, and compare flags to match.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ */
+ function baseIsMatch(object, source, matchData, customizer) {
+ var index = matchData.length,
+ length = index,
+ noCustomizer = !customizer;
+
+ if (object == null) {
+ return !length;
+ }
+ object = Object(object);
+ while (index--) {
+ var data = matchData[index];
+ if ((noCustomizer && data[2])
+ ? data[1] !== object[data[0]]
+ : !(data[0] in object)
+ ) {
+ return false;
+ }
+ }
+ while (++index < length) {
+ data = matchData[index];
+ var key = data[0],
+ objValue = object[key],
+ srcValue = data[1];
+
+ if (noCustomizer && data[2]) {
+ if (objValue === undefined && !(key in object)) {
+ return false;
+ }
+ } else {
+ var stack = new Stack;
+ if (customizer) {
+ var result = customizer(objValue, srcValue, key, object, source, stack);
+ }
+ if (!(result === undefined
+ ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
+ : result
+ )) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * The base implementation of `_.isNative` without bad shim checks.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function,
+ * else `false`.
+ */
+ function baseIsNative(value) {
+ if (!isObject(value) || isMasked(value)) {
+ return false;
+ }
+ var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
+ return pattern.test(toSource(value));
+ }
+
+ /**
+ * The base implementation of `_.isRegExp` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
+ */
+ function baseIsRegExp(value) {
+ return isObjectLike(value) && baseGetTag(value) == regexpTag;
+ }
+
+ /**
+ * The base implementation of `_.isSet` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a set, else `false`.
+ */
+ function baseIsSet(value) {
+ return isObjectLike(value) && getTag(value) == setTag;
+ }
+
+ /**
+ * The base implementation of `_.isTypedArray` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
+ */
+ function baseIsTypedArray(value) {
+ return isObjectLike(value) &&
+ isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
+ }
+
+ /**
+ * The base implementation of `_.iteratee`.
+ *
+ * @private
+ * @param {*} [value=_.identity] The value to convert to an iteratee.
+ * @returns {Function} Returns the iteratee.
+ */
+ function baseIteratee(value) {
+ // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
+ // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
+ if (typeof value == 'function') {
+ return value;
+ }
+ if (value == null) {
+ return identity;
+ }
+ if (typeof value == 'object') {
+ return isArray(value)
+ ? baseMatchesProperty(value[0], value[1])
+ : baseMatches(value);
+ }
+ return property(value);
+ }
+
+ /**
+ * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function baseKeys(object) {
+ if (!isPrototype(object)) {
+ return nativeKeys(object);
+ }
+ var result = [];
+ for (var key in Object(object)) {
+ if (hasOwnProperty.call(object, key) && key != 'constructor') {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function baseKeysIn(object) {
+ if (!isObject(object)) {
+ return nativeKeysIn(object);
+ }
+ var isProto = isPrototype(object),
+ result = [];
+
+ for (var key in object) {
+ if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.lt` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than `other`,
+ * else `false`.
+ */
+ function baseLt(value, other) {
+ return value < other;
+ }
+
+ /**
+ * The base implementation of `_.map` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function baseMap(collection, iteratee) {
+ var index = -1,
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value, key, collection) {
+ result[++index] = iteratee(value, key, collection);
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.matches` which doesn't clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new spec function.
+ */
+ function baseMatches(source) {
+ var matchData = getMatchData(source);
+ if (matchData.length == 1 && matchData[0][2]) {
+ return matchesStrictComparable(matchData[0][0], matchData[0][1]);
+ }
+ return function(object) {
+ return object === source || baseIsMatch(object, source, matchData);
+ };
+ }
+
+ /**
+ * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
+ *
+ * @private
+ * @param {string} path The path of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new spec function.
+ */
+ function baseMatchesProperty(path, srcValue) {
+ if (isKey(path) && isStrictComparable(srcValue)) {
+ return matchesStrictComparable(toKey(path), srcValue);
+ }
+ return function(object) {
+ var objValue = get(object, path);
+ return (objValue === undefined && objValue === srcValue)
+ ? hasIn(object, path)
+ : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
+ };
+ }
+
+ /**
+ * The base implementation of `_.merge` without support for multiple sources.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} [customizer] The function to customize merged values.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ */
+ function baseMerge(object, source, srcIndex, customizer, stack) {
+ if (object === source) {
+ return;
+ }
+ baseFor(source, function(srcValue, key) {
+ if (isObject(srcValue)) {
+ stack || (stack = new Stack);
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
+ }
+ else {
+ var newValue = customizer
+ ? customizer(object[key], srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ if (newValue === undefined) {
+ newValue = srcValue;
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ }, keysIn);
+ }
+
+ /**
+ * A specialized version of `baseMerge` for arrays and objects which performs
+ * deep merges and tracks traversed objects enabling objects with circular
+ * references to be merged.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {string} key The key of the value to merge.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} mergeFunc The function to merge values.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ */
+ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
+ var objValue = object[key],
+ srcValue = source[key],
+ stacked = stack.get(srcValue);
+
+ if (stacked) {
+ assignMergeValue(object, key, stacked);
+ return;
+ }
+ var newValue = customizer
+ ? customizer(objValue, srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ var isCommon = newValue === undefined;
+
+ if (isCommon) {
+ var isArr = isArray(srcValue),
+ isBuff = !isArr && isBuffer(srcValue),
+ isTyped = !isArr && !isBuff && isTypedArray(srcValue);
+
+ newValue = srcValue;
+ if (isArr || isBuff || isTyped) {
+ if (isArray(objValue)) {
+ newValue = objValue;
+ }
+ else if (isArrayLikeObject(objValue)) {
+ newValue = copyArray(objValue);
+ }
+ else if (isBuff) {
+ isCommon = false;
+ newValue = cloneBuffer(srcValue, true);
+ }
+ else if (isTyped) {
+ isCommon = false;
+ newValue = cloneTypedArray(srcValue, true);
+ }
+ else {
+ newValue = [];
+ }
+ }
+ else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+ newValue = objValue;
+ if (isArguments(objValue)) {
+ newValue = toPlainObject(objValue);
+ }
+ else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
+ newValue = initCloneObject(srcValue);
+ }
+ }
+ else {
+ isCommon = false;
+ }
+ }
+ if (isCommon) {
+ // Recursively merge objects and arrays (susceptible to call stack limits).
+ stack.set(srcValue, newValue);
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
+ stack['delete'](srcValue);
+ }
+ assignMergeValue(object, key, newValue);
+ }
+
+ /**
+ * The base implementation of `_.nth` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {number} n The index of the element to return.
+ * @returns {*} Returns the nth element of `array`.
+ */
+ function baseNth(array, n) {
+ var length = array.length;
+ if (!length) {
+ return;
+ }
+ n += n < 0 ? length : 0;
+ return isIndex(n, length) ? array[n] : undefined;
+ }
+
+ /**
+ * The base implementation of `_.orderBy` without param guards.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+ * @param {string[]} orders The sort orders of `iteratees`.
+ * @returns {Array} Returns the new sorted array.
+ */
+ function baseOrderBy(collection, iteratees, orders) {
+ var index = -1;
+ iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));
+
+ var result = baseMap(collection, function(value, key, collection) {
+ var criteria = arrayMap(iteratees, function(iteratee) {
+ return iteratee(value);
+ });
+ return { 'criteria': criteria, 'index': ++index, 'value': value };
+ });
+
+ return baseSortBy(result, function(object, other) {
+ return compareMultiple(object, other, orders);
+ });
+ }
+
+ /**
+ * The base implementation of `_.pick` without support for individual
+ * property identifiers.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {string[]} paths The property paths to pick.
+ * @returns {Object} Returns the new object.
+ */
+ function basePick(object, paths) {
+ return basePickBy(object, paths, function(value, path) {
+ return hasIn(object, path);
+ });
+ }
+
+ /**
+ * The base implementation of `_.pickBy` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {string[]} paths The property paths to pick.
+ * @param {Function} predicate The function invoked per property.
+ * @returns {Object} Returns the new object.
+ */
+ function basePickBy(object, paths, predicate) {
+ var index = -1,
+ length = paths.length,
+ result = {};
+
+ while (++index < length) {
+ var path = paths[index],
+ value = baseGet(object, path);
+
+ if (predicate(value, path)) {
+ baseSet(result, castPath(path, object), value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `baseProperty` which supports deep paths.
+ *
+ * @private
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new accessor function.
+ */
+ function basePropertyDeep(path) {
+ return function(object) {
+ return baseGet(object, path);
+ };
+ }
+
+ /**
+ * The base implementation of `_.pullAllBy` without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns `array`.
+ */
+ function basePullAll(array, values, iteratee, comparator) {
+ var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
+ index = -1,
+ length = values.length,
+ seen = array;
+
+ if (array === values) {
+ values = copyArray(values);
+ }
+ if (iteratee) {
+ seen = arrayMap(array, baseUnary(iteratee));
+ }
+ while (++index < length) {
+ var fromIndex = 0,
+ value = values[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
+ if (seen !== array) {
+ splice.call(seen, fromIndex, 1);
+ }
+ splice.call(array, fromIndex, 1);
+ }
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.pullAt` without support for individual
+ * indexes or capturing the removed elements.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {number[]} indexes The indexes of elements to remove.
+ * @returns {Array} Returns `array`.
+ */
+ function basePullAt(array, indexes) {
+ var length = array ? indexes.length : 0,
+ lastIndex = length - 1;
+
+ while (length--) {
+ var index = indexes[length];
+ if (length == lastIndex || index !== previous) {
+ var previous = index;
+ if (isIndex(index)) {
+ splice.call(array, index, 1);
+ } else {
+ baseUnset(array, index);
+ }
+ }
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.random` without support for returning
+ * floating-point numbers.
+ *
+ * @private
+ * @param {number} lower The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the random number.
+ */
+ function baseRandom(lower, upper) {
+ return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
+ }
+
+ /**
+ * The base implementation of `_.range` and `_.rangeRight` which doesn't
+ * coerce arguments.
+ *
+ * @private
+ * @param {number} start The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} step The value to increment or decrement by.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the range of numbers.
+ */
+ function baseRange(start, end, step, fromRight) {
+ var index = -1,
+ length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
+ result = Array(length);
+
+ while (length--) {
+ result[fromRight ? length : ++index] = start;
+ start += step;
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.repeat` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {string} string The string to repeat.
+ * @param {number} n The number of times to repeat the string.
+ * @returns {string} Returns the repeated string.
+ */
+ function baseRepeat(string, n) {
+ var result = '';
+ if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
+ return result;
+ }
+ // Leverage the exponentiation by squaring algorithm for a faster repeat.
+ // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
+ do {
+ if (n % 2) {
+ result += string;
+ }
+ n = nativeFloor(n / 2);
+ if (n) {
+ string += string;
+ }
+ } while (n);
+
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.rest` which doesn't validate or coerce arguments.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
+ */
+ function baseRest(func, start) {
+ return setToString(overRest(func, start, identity), func + '');
+ }
+
+ /**
+ * The base implementation of `_.sample`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to sample.
+ * @returns {*} Returns the random element.
+ */
+ function baseSample(collection) {
+ return arraySample(values(collection));
+ }
+
+ /**
+ * The base implementation of `_.sampleSize` without param guards.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to sample.
+ * @param {number} n The number of elements to sample.
+ * @returns {Array} Returns the random elements.
+ */
+ function baseSampleSize(collection, n) {
+ var array = values(collection);
+ return shuffleSelf(array, baseClamp(n, 0, array.length));
+ }
+
+ /**
+ * The base implementation of `_.set`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize path creation.
+ * @returns {Object} Returns `object`.
+ */
+ function baseSet(object, path, value, customizer) {
+ if (!isObject(object)) {
+ return object;
+ }
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length,
+ lastIndex = length - 1,
+ nested = object;
+
+ while (nested != null && ++index < length) {
+ var key = toKey(path[index]),
+ newValue = value;
+
+ if (index != lastIndex) {
+ var objValue = nested[key];
+ newValue = customizer ? customizer(objValue, key, nested) : undefined;
+ if (newValue === undefined) {
+ newValue = isObject(objValue)
+ ? objValue
+ : (isIndex(path[index + 1]) ? [] : {});
+ }
+ }
+ assignValue(nested, key, newValue);
+ nested = nested[key];
+ }
+ return object;
+ }
+
+ /**
+ * The base implementation of `setData` without support for hot loop shorting.
+ *
+ * @private
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
+ */
+ var baseSetData = !metaMap ? identity : function(func, data) {
+ metaMap.set(func, data);
+ return func;
+ };
+
+ /**
+ * The base implementation of `setToString` without support for hot loop shorting.
+ *
+ * @private
+ * @param {Function} func The function to modify.
+ * @param {Function} string The `toString` result.
+ * @returns {Function} Returns `func`.
+ */
+ var baseSetToString = !defineProperty ? identity : function(func, string) {
+ return defineProperty(func, 'toString', {
+ 'configurable': true,
+ 'enumerable': false,
+ 'value': constant(string),
+ 'writable': true
+ });
+ };
+
+ /**
+ * The base implementation of `_.shuffle`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ */
+ function baseShuffle(collection) {
+ return shuffleSelf(values(collection));
+ }
+
+ /**
+ * The base implementation of `_.slice` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseSlice(array, start, end) {
+ var index = -1,
+ length = array.length;
+
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = end > length ? length : end;
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : ((end - start) >>> 0);
+ start >>>= 0;
+
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = array[index + start];
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.some` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function baseSome(collection, predicate) {
+ var result;
+
+ baseEach(collection, function(value, index, collection) {
+ result = predicate(value, index, collection);
+ return !result;
+ });
+ return !!result;
+ }
+
+ /**
+ * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
+ * performs a binary search of `array` to determine the index at which `value`
+ * should be inserted into `array` in order to maintain its sort order.
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function baseSortedIndex(array, value, retHighest) {
+ var low = 0,
+ high = array == null ? low : array.length;
+
+ if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
+ while (low < high) {
+ var mid = (low + high) >>> 1,
+ computed = array[mid];
+
+ if (computed !== null && !isSymbol(computed) &&
+ (retHighest ? (computed <= value) : (computed < value))) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return high;
+ }
+ return baseSortedIndexBy(array, value, identity, retHighest);
+ }
+
+ /**
+ * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
+ * which invokes `iteratee` for `value` and each element of `array` to compute
+ * their sort ranking. The iteratee is invoked with one argument; (value).
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} iteratee The iteratee invoked per element.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function baseSortedIndexBy(array, value, iteratee, retHighest) {
+ value = iteratee(value);
+
+ var low = 0,
+ high = array == null ? 0 : array.length,
+ valIsNaN = value !== value,
+ valIsNull = value === null,
+ valIsSymbol = isSymbol(value),
+ valIsUndefined = value === undefined;
+
+ while (low < high) {
+ var mid = nativeFloor((low + high) / 2),
+ computed = iteratee(array[mid]),
+ othIsDefined = computed !== undefined,
+ othIsNull = computed === null,
+ othIsReflexive = computed === computed,
+ othIsSymbol = isSymbol(computed);
+
+ if (valIsNaN) {
+ var setLow = retHighest || othIsReflexive;
+ } else if (valIsUndefined) {
+ setLow = othIsReflexive && (retHighest || othIsDefined);
+ } else if (valIsNull) {
+ setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
+ } else if (valIsSymbol) {
+ setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
+ } else if (othIsNull || othIsSymbol) {
+ setLow = false;
+ } else {
+ setLow = retHighest ? (computed <= value) : (computed < value);
+ }
+ if (setLow) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return nativeMin(high, MAX_ARRAY_INDEX);
+ }
+
+ /**
+ * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
+ * support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ */
+ function baseSortedUniq(array, iteratee) {
+ var index = -1,
+ length = array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ if (!index || !eq(computed, seen)) {
+ var seen = computed;
+ result[resIndex++] = value === 0 ? 0 : value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.toNumber` which doesn't ensure correct
+ * conversions of binary, hexadecimal, or octal string values.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ */
+ function baseToNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ return +value;
+ }
+
+ /**
+ * The base implementation of `_.toString` which doesn't convert nullish
+ * values to empty strings.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {string} Returns the string.
+ */
+ function baseToString(value) {
+ // Exit early for strings to avoid a performance hit in some environments.
+ if (typeof value == 'string') {
+ return value;
+ }
+ if (isArray(value)) {
+ // Recursively convert values (susceptible to call stack limits).
+ return arrayMap(value, baseToString) + '';
+ }
+ if (isSymbol(value)) {
+ return symbolToString ? symbolToString.call(value) : '';
+ }
+ var result = (value + '');
+ return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
+ }
+
+ /**
+ * The base implementation of `_.uniqBy` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ */
+ function baseUniq(array, iteratee, comparator) {
+ var index = -1,
+ includes = arrayIncludes,
+ length = array.length,
+ isCommon = true,
+ result = [],
+ seen = result;
+
+ if (comparator) {
+ isCommon = false;
+ includes = arrayIncludesWith;
+ }
+ else if (length >= LARGE_ARRAY_SIZE) {
+ var set = iteratee ? null : createSet(array);
+ if (set) {
+ return setToArray(set);
+ }
+ isCommon = false;
+ includes = cacheHas;
+ seen = new SetCache;
+ }
+ else {
+ seen = iteratee ? [] : result;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ value = (comparator || value !== 0) ? value : 0;
+ if (isCommon && computed === computed) {
+ var seenIndex = seen.length;
+ while (seenIndex--) {
+ if (seen[seenIndex] === computed) {
+ continue outer;
+ }
+ }
+ if (iteratee) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ else if (!includes(seen, computed, comparator)) {
+ if (seen !== result) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.unset`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The property path to unset.
+ * @returns {boolean} Returns `true` if the property is deleted, else `false`.
+ */
+ function baseUnset(object, path) {
+ path = castPath(path, object);
+ object = parent(object, path);
+ return object == null || delete object[toKey(last(path))];
+ }
+
+ /**
+ * The base implementation of `_.update`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to update.
+ * @param {Function} updater The function to produce the updated value.
+ * @param {Function} [customizer] The function to customize path creation.
+ * @returns {Object} Returns `object`.
+ */
+ function baseUpdate(object, path, updater, customizer) {
+ return baseSet(object, path, updater(baseGet(object, path)), customizer);
+ }
+
+ /**
+ * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
+ * without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseWhile(array, predicate, isDrop, fromRight) {
+ var length = array.length,
+ index = fromRight ? length : -1;
+
+ while ((fromRight ? index-- : ++index < length) &&
+ predicate(array[index], index, array)) {}
+
+ return isDrop
+ ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
+ : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
+ }
+
+ /**
+ * The base implementation of `wrapperValue` which returns the result of
+ * performing a sequence of actions on the unwrapped `value`, where each
+ * successive action is supplied the return value of the previous.
+ *
+ * @private
+ * @param {*} value The unwrapped value.
+ * @param {Array} actions Actions to perform to resolve the unwrapped value.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseWrapperValue(value, actions) {
+ var result = value;
+ if (result instanceof LazyWrapper) {
+ result = result.value();
+ }
+ return arrayReduce(actions, function(result, action) {
+ return action.func.apply(action.thisArg, arrayPush([result], action.args));
+ }, result);
+ }
+
+ /**
+ * The base implementation of methods like `_.xor`, without support for
+ * iteratee shorthands, that accepts an array of arrays to inspect.
+ *
+ * @private
+ * @param {Array} arrays The arrays to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of values.
+ */
+ function baseXor(arrays, iteratee, comparator) {
+ var length = arrays.length;
+ if (length < 2) {
+ return length ? baseUniq(arrays[0]) : [];
+ }
+ var index = -1,
+ result = Array(length);
+
+ while (++index < length) {
+ var array = arrays[index],
+ othIndex = -1;
+
+ while (++othIndex < length) {
+ if (othIndex != index) {
+ result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
+ }
+ }
+ }
+ return baseUniq(baseFlatten(result, 1), iteratee, comparator);
+ }
+
+ /**
+ * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
+ *
+ * @private
+ * @param {Array} props The property identifiers.
+ * @param {Array} values The property values.
+ * @param {Function} assignFunc The function to assign values.
+ * @returns {Object} Returns the new object.
+ */
+ function baseZipObject(props, values, assignFunc) {
+ var index = -1,
+ length = props.length,
+ valsLength = values.length,
+ result = {};
+
+ while (++index < length) {
+ var value = index < valsLength ? values[index] : undefined;
+ assignFunc(result, props[index], value);
+ }
+ return result;
+ }
+
+ /**
+ * Casts `value` to an empty array if it's not an array like object.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Array|Object} Returns the cast array-like object.
+ */
+ function castArrayLikeObject(value) {
+ return isArrayLikeObject(value) ? value : [];
+ }
+
+ /**
+ * Casts `value` to `identity` if it's not a function.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Function} Returns cast function.
+ */
+ function castFunction(value) {
+ return typeof value == 'function' ? value : identity;
+ }
+
+ /**
+ * Casts `value` to a path array if it's not one.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {Array} Returns the cast property path array.
+ */
+ function castPath(value, object) {
+ if (isArray(value)) {
+ return value;
+ }
+ return isKey(value, object) ? [value] : stringToPath(toString(value));
+ }
+
+ /**
+ * A `baseRest` alias which can be replaced with `identity` by module
+ * replacement plugins.
+ *
+ * @private
+ * @type {Function}
+ * @param {Function} func The function to apply a rest parameter to.
+ * @returns {Function} Returns the new function.
+ */
+ var castRest = baseRest;
+
+ /**
+ * Casts `array` to a slice if it's needed.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {number} start The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the cast slice.
+ */
+ function castSlice(array, start, end) {
+ var length = array.length;
+ end = end === undefined ? length : end;
+ return (!start && end >= length) ? array : baseSlice(array, start, end);
+ }
+
+ /**
+ * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
+ *
+ * @private
+ * @param {number|Object} id The timer id or timeout object of the timer to clear.
+ */
+ var clearTimeout = ctxClearTimeout || function(id) {
+ return root.clearTimeout(id);
+ };
+
+ /**
+ * Creates a clone of `buffer`.
+ *
+ * @private
+ * @param {Buffer} buffer The buffer to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Buffer} Returns the cloned buffer.
+ */
+ function cloneBuffer(buffer, isDeep) {
+ if (isDeep) {
+ return buffer.slice();
+ }
+ var length = buffer.length,
+ result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
+
+ buffer.copy(result);
+ return result;
+ }
+
+ /**
+ * Creates a clone of `arrayBuffer`.
+ *
+ * @private
+ * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
+ */
+ function cloneArrayBuffer(arrayBuffer) {
+ var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
+ new Uint8Array(result).set(new Uint8Array(arrayBuffer));
+ return result;
+ }
+
+ /**
+ * Creates a clone of `dataView`.
+ *
+ * @private
+ * @param {Object} dataView The data view to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned data view.
+ */
+ function cloneDataView(dataView, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
+ return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
+ }
+
+ /**
+ * Creates a clone of `map`.
+ *
+ * @private
+ * @param {Object} map The map to clone.
+ * @param {Function} cloneFunc The function to clone values.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned map.
+ */
+ function cloneMap(map, isDeep, cloneFunc) {
+ var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
+ return arrayReduce(array, addMapEntry, new map.constructor);
+ }
+
+ /**
+ * Creates a clone of `regexp`.
+ *
+ * @private
+ * @param {Object} regexp The regexp to clone.
+ * @returns {Object} Returns the cloned regexp.
+ */
+ function cloneRegExp(regexp) {
+ var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
+ result.lastIndex = regexp.lastIndex;
+ return result;
+ }
+
+ /**
+ * Creates a clone of `set`.
+ *
+ * @private
+ * @param {Object} set The set to clone.
+ * @param {Function} cloneFunc The function to clone values.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned set.
+ */
+ function cloneSet(set, isDeep, cloneFunc) {
+ var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
+ return arrayReduce(array, addSetEntry, new set.constructor);
+ }
+
+ /**
+ * Creates a clone of the `symbol` object.
+ *
+ * @private
+ * @param {Object} symbol The symbol object to clone.
+ * @returns {Object} Returns the cloned symbol object.
+ */
+ function cloneSymbol(symbol) {
+ return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
+ }
+
+ /**
+ * Creates a clone of `typedArray`.
+ *
+ * @private
+ * @param {Object} typedArray The typed array to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned typed array.
+ */
+ function cloneTypedArray(typedArray, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
+ return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
+ }
+
+ /**
+ * Compares values to sort them in ascending order.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {number} Returns the sort order indicator for `value`.
+ */
+ function compareAscending(value, other) {
+ if (value !== other) {
+ var valIsDefined = value !== undefined,
+ valIsNull = value === null,
+ valIsReflexive = value === value,
+ valIsSymbol = isSymbol(value);
+
+ var othIsDefined = other !== undefined,
+ othIsNull = other === null,
+ othIsReflexive = other === other,
+ othIsSymbol = isSymbol(other);
+
+ if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
+ (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
+ (valIsNull && othIsDefined && othIsReflexive) ||
+ (!valIsDefined && othIsReflexive) ||
+ !valIsReflexive) {
+ return 1;
+ }
+ if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
+ (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
+ (othIsNull && valIsDefined && valIsReflexive) ||
+ (!othIsDefined && valIsReflexive) ||
+ !othIsReflexive) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Used by `_.orderBy` to compare multiple properties of a value to another
+ * and stable sort them.
+ *
+ * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
+ * specify an order of "desc" for descending or "asc" for ascending sort order
+ * of corresponding values.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {boolean[]|string[]} orders The order to sort by for each property.
+ * @returns {number} Returns the sort order indicator for `object`.
+ */
+ function compareMultiple(object, other, orders) {
+ var index = -1,
+ objCriteria = object.criteria,
+ othCriteria = other.criteria,
+ length = objCriteria.length,
+ ordersLength = orders.length;
+
+ while (++index < length) {
+ var result = compareAscending(objCriteria[index], othCriteria[index]);
+ if (result) {
+ if (index >= ordersLength) {
+ return result;
+ }
+ var order = orders[index];
+ return result * (order == 'desc' ? -1 : 1);
+ }
+ }
+ // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+ // that causes it, under certain circumstances, to provide the same value for
+ // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
+ // for more details.
+ //
+ // This also ensures a stable sort in V8 and other engines.
+ // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
+ return object.index - other.index;
+ }
+
+ /**
+ * Creates an array that is the composition of partially applied arguments,
+ * placeholders, and provided arguments into a single array of arguments.
+ *
+ * @private
+ * @param {Array} args The provided arguments.
+ * @param {Array} partials The arguments to prepend to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @params {boolean} [isCurried] Specify composing for a curried function.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgs(args, partials, holders, isCurried) {
+ var argsIndex = -1,
+ argsLength = args.length,
+ holdersLength = holders.length,
+ leftIndex = -1,
+ leftLength = partials.length,
+ rangeLength = nativeMax(argsLength - holdersLength, 0),
+ result = Array(leftLength + rangeLength),
+ isUncurried = !isCurried;
+
+ while (++leftIndex < leftLength) {
+ result[leftIndex] = partials[leftIndex];
+ }
+ while (++argsIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result[holders[argsIndex]] = args[argsIndex];
+ }
+ }
+ while (rangeLength--) {
+ result[leftIndex++] = args[argsIndex++];
+ }
+ return result;
+ }
+
+ /**
+ * This function is like `composeArgs` except that the arguments composition
+ * is tailored for `_.partialRight`.
+ *
+ * @private
+ * @param {Array} args The provided arguments.
+ * @param {Array} partials The arguments to append to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @params {boolean} [isCurried] Specify composing for a curried function.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgsRight(args, partials, holders, isCurried) {
+ var argsIndex = -1,
+ argsLength = args.length,
+ holdersIndex = -1,
+ holdersLength = holders.length,
+ rightIndex = -1,
+ rightLength = partials.length,
+ rangeLength = nativeMax(argsLength - holdersLength, 0),
+ result = Array(rangeLength + rightLength),
+ isUncurried = !isCurried;
+
+ while (++argsIndex < rangeLength) {
+ result[argsIndex] = args[argsIndex];
+ }
+ var offset = argsIndex;
+ while (++rightIndex < rightLength) {
+ result[offset + rightIndex] = partials[rightIndex];
+ }
+ while (++holdersIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result[offset + holders[holdersIndex]] = args[argsIndex++];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Copies the values of `source` to `array`.
+ *
+ * @private
+ * @param {Array} source The array to copy values from.
+ * @param {Array} [array=[]] The array to copy values to.
+ * @returns {Array} Returns `array`.
+ */
+ function copyArray(source, array) {
+ var index = -1,
+ length = source.length;
+
+ array || (array = Array(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+ }
+
+ /**
+ * Copies properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy properties from.
+ * @param {Array} props The property identifiers to copy.
+ * @param {Object} [object={}] The object to copy properties to.
+ * @param {Function} [customizer] The function to customize copied values.
+ * @returns {Object} Returns `object`.
+ */
+ function copyObject(source, props, object, customizer) {
+ var isNew = !object;
+ object || (object = {});
+
+ var index = -1,
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+
+ var newValue = customizer
+ ? customizer(object[key], source[key], key, object, source)
+ : undefined;
+
+ if (newValue === undefined) {
+ newValue = source[key];
+ }
+ if (isNew) {
+ baseAssignValue(object, key, newValue);
+ } else {
+ assignValue(object, key, newValue);
+ }
+ }
+ return object;
+ }
+
+ /**
+ * Copies own symbols of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy symbols from.
+ * @param {Object} [object={}] The object to copy symbols to.
+ * @returns {Object} Returns `object`.
+ */
+ function copySymbols(source, object) {
+ return copyObject(source, getSymbols(source), object);
+ }
+
+ /**
+ * Copies own and inherited symbols of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy symbols from.
+ * @param {Object} [object={}] The object to copy symbols to.
+ * @returns {Object} Returns `object`.
+ */
+ function copySymbolsIn(source, object) {
+ return copyObject(source, getSymbolsIn(source), object);
+ }
+
+ /**
+ * Creates a function like `_.groupBy`.
+ *
+ * @private
+ * @param {Function} setter The function to set accumulator values.
+ * @param {Function} [initializer] The accumulator object initializer.
+ * @returns {Function} Returns the new aggregator function.
+ */
+ function createAggregator(setter, initializer) {
+ return function(collection, iteratee) {
+ var func = isArray(collection) ? arrayAggregator : baseAggregator,
+ accumulator = initializer ? initializer() : {};
+
+ return func(collection, setter, getIteratee(iteratee, 2), accumulator);
+ };
+ }
+
+ /**
+ * Creates a function like `_.assign`.
+ *
+ * @private
+ * @param {Function} assigner The function to assign values.
+ * @returns {Function} Returns the new assigner function.
+ */
+ function createAssigner(assigner) {
+ return baseRest(function(object, sources) {
+ var index = -1,
+ length = sources.length,
+ customizer = length > 1 ? sources[length - 1] : undefined,
+ guard = length > 2 ? sources[2] : undefined;
+
+ customizer = (assigner.length > 3 && typeof customizer == 'function')
+ ? (length--, customizer)
+ : undefined;
+
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? undefined : customizer;
+ length = 1;
+ }
+ object = Object(object);
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, index, customizer);
+ }
+ }
+ return object;
+ });
+ }
+
+ /**
+ * Creates a `baseEach` or `baseEachRight` function.
+ *
+ * @private
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseEach(eachFunc, fromRight) {
+ return function(collection, iteratee) {
+ if (collection == null) {
+ return collection;
+ }
+ if (!isArrayLike(collection)) {
+ return eachFunc(collection, iteratee);
+ }
+ var length = collection.length,
+ index = fromRight ? length : -1,
+ iterable = Object(collection);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (iteratee(iterable[index], index, iterable) === false) {
+ break;
+ }
+ }
+ return collection;
+ };
+ }
+
+ /**
+ * Creates a base function for methods like `_.forIn` and `_.forOwn`.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseFor(fromRight) {
+ return function(object, iteratee, keysFunc) {
+ var index = -1,
+ iterable = Object(object),
+ props = keysFunc(object),
+ length = props.length;
+
+ while (length--) {
+ var key = props[fromRight ? length : ++index];
+ if (iteratee(iterable[key], key, iterable) === false) {
+ break;
+ }
+ }
+ return object;
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with the optional `this`
+ * binding of `thisArg`.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createBind(func, bitmask, thisArg) {
+ var isBind = bitmask & WRAP_BIND_FLAG,
+ Ctor = createCtor(func);
+
+ function wrapper() {
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return fn.apply(isBind ? thisArg : this, arguments);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a function like `_.lowerFirst`.
+ *
+ * @private
+ * @param {string} methodName The name of the `String` case method to use.
+ * @returns {Function} Returns the new case function.
+ */
+ function createCaseFirst(methodName) {
+ return function(string) {
+ string = toString(string);
+
+ var strSymbols = hasUnicode(string)
+ ? stringToArray(string)
+ : undefined;
+
+ var chr = strSymbols
+ ? strSymbols[0]
+ : string.charAt(0);
+
+ var trailing = strSymbols
+ ? castSlice(strSymbols, 1).join('')
+ : string.slice(1);
+
+ return chr[methodName]() + trailing;
+ };
+ }
+
+ /**
+ * Creates a function like `_.camelCase`.
+ *
+ * @private
+ * @param {Function} callback The function to combine each word.
+ * @returns {Function} Returns the new compounder function.
+ */
+ function createCompounder(callback) {
+ return function(string) {
+ return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
+ };
+ }
+
+ /**
+ * Creates a function that produces an instance of `Ctor` regardless of
+ * whether it was invoked as part of a `new` expression or by `call` or `apply`.
+ *
+ * @private
+ * @param {Function} Ctor The constructor to wrap.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createCtor(Ctor) {
+ return function() {
+ // Use a `switch` statement to work with class constructors. See
+ // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
+ // for more details.
+ var args = arguments;
+ switch (args.length) {
+ case 0: return new Ctor;
+ case 1: return new Ctor(args[0]);
+ case 2: return new Ctor(args[0], args[1]);
+ case 3: return new Ctor(args[0], args[1], args[2]);
+ case 4: return new Ctor(args[0], args[1], args[2], args[3]);
+ case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
+ case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ }
+ var thisBinding = baseCreate(Ctor.prototype),
+ result = Ctor.apply(thisBinding, args);
+
+ // Mimic the constructor's `return` behavior.
+ // See https://es5.github.io/#x13.2.2 for more details.
+ return isObject(result) ? result : thisBinding;
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to enable currying.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {number} arity The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createCurry(func, bitmask, arity) {
+ var Ctor = createCtor(func);
+
+ function wrapper() {
+ var length = arguments.length,
+ args = Array(length),
+ index = length,
+ placeholder = getHolder(wrapper);
+
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
+ ? []
+ : replaceHolders(args, placeholder);
+
+ length -= holders.length;
+ if (length < arity) {
+ return createRecurry(
+ func, bitmask, createHybrid, wrapper.placeholder, undefined,
+ args, holders, undefined, undefined, arity - length);
+ }
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return apply(fn, this, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a `_.find` or `_.findLast` function.
+ *
+ * @private
+ * @param {Function} findIndexFunc The function to find the collection index.
+ * @returns {Function} Returns the new find function.
+ */
+ function createFind(findIndexFunc) {
+ return function(collection, predicate, fromIndex) {
+ var iterable = Object(collection);
+ if (!isArrayLike(collection)) {
+ var iteratee = getIteratee(predicate, 3);
+ collection = keys(collection);
+ predicate = function(key) { return iteratee(iterable[key], key, iterable); };
+ }
+ var index = findIndexFunc(collection, predicate, fromIndex);
+ return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
+ };
+ }
+
+ /**
+ * Creates a `_.flow` or `_.flowRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new flow function.
+ */
+ function createFlow(fromRight) {
+ return flatRest(function(funcs) {
+ var length = funcs.length,
+ index = length,
+ prereq = LodashWrapper.prototype.thru;
+
+ if (fromRight) {
+ funcs.reverse();
+ }
+ while (index--) {
+ var func = funcs[index];
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
+ var wrapper = new LodashWrapper([], true);
+ }
+ }
+ index = wrapper ? index : length;
+ while (++index < length) {
+ func = funcs[index];
+
+ var funcName = getFuncName(func),
+ data = funcName == 'wrapper' ? getData(func) : undefined;
+
+ if (data && isLaziable(data[0]) &&
+ data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
+ !data[4].length && data[9] == 1
+ ) {
+ wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
+ } else {
+ wrapper = (func.length == 1 && isLaziable(func))
+ ? wrapper[funcName]()
+ : wrapper.thru(func);
+ }
+ }
+ return function() {
+ var args = arguments,
+ value = args[0];
+
+ if (wrapper && args.length == 1 && isArray(value)) {
+ return wrapper.plant(value).value();
+ }
+ var index = 0,
+ result = length ? funcs[index].apply(this, args) : value;
+
+ while (++index < length) {
+ result = funcs[index].call(this, result);
+ }
+ return result;
+ };
+ });
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with optional `this`
+ * binding of `thisArg`, partial application, and currying.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to prepend to those provided to
+ * the new function.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [partialsRight] The arguments to append to those provided
+ * to the new function.
+ * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
+ var isAry = bitmask & WRAP_ARY_FLAG,
+ isBind = bitmask & WRAP_BIND_FLAG,
+ isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
+ isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
+ isFlip = bitmask & WRAP_FLIP_FLAG,
+ Ctor = isBindKey ? undefined : createCtor(func);
+
+ function wrapper() {
+ var length = arguments.length,
+ args = Array(length),
+ index = length;
+
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ if (isCurried) {
+ var placeholder = getHolder(wrapper),
+ holdersCount = countHolders(args, placeholder);
+ }
+ if (partials) {
+ args = composeArgs(args, partials, holders, isCurried);
+ }
+ if (partialsRight) {
+ args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
+ }
+ length -= holdersCount;
+ if (isCurried && length < arity) {
+ var newHolders = replaceHolders(args, placeholder);
+ return createRecurry(
+ func, bitmask, createHybrid, wrapper.placeholder, thisArg,
+ args, newHolders, argPos, ary, arity - length
+ );
+ }
+ var thisBinding = isBind ? thisArg : this,
+ fn = isBindKey ? thisBinding[func] : func;
+
+ length = args.length;
+ if (argPos) {
+ args = reorder(args, argPos);
+ } else if (isFlip && length > 1) {
+ args.reverse();
+ }
+ if (isAry && ary < length) {
+ args.length = ary;
+ }
+ if (this && this !== root && this instanceof wrapper) {
+ fn = Ctor || createCtor(fn);
+ }
+ return fn.apply(thisBinding, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a function like `_.invertBy`.
+ *
+ * @private
+ * @param {Function} setter The function to set accumulator values.
+ * @param {Function} toIteratee The function to resolve iteratees.
+ * @returns {Function} Returns the new inverter function.
+ */
+ function createInverter(setter, toIteratee) {
+ return function(object, iteratee) {
+ return baseInverter(object, setter, toIteratee(iteratee), {});
+ };
+ }
+
+ /**
+ * Creates a function that performs a mathematical operation on two values.
+ *
+ * @private
+ * @param {Function} operator The function to perform the operation.
+ * @param {number} [defaultValue] The value used for `undefined` arguments.
+ * @returns {Function} Returns the new mathematical operation function.
+ */
+ function createMathOperation(operator, defaultValue) {
+ return function(value, other) {
+ var result;
+ if (value === undefined && other === undefined) {
+ return defaultValue;
+ }
+ if (value !== undefined) {
+ result = value;
+ }
+ if (other !== undefined) {
+ if (result === undefined) {
+ return other;
+ }
+ if (typeof value == 'string' || typeof other == 'string') {
+ value = baseToString(value);
+ other = baseToString(other);
+ } else {
+ value = baseToNumber(value);
+ other = baseToNumber(other);
+ }
+ result = operator(value, other);
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function like `_.over`.
+ *
+ * @private
+ * @param {Function} arrayFunc The function to iterate over iteratees.
+ * @returns {Function} Returns the new over function.
+ */
+ function createOver(arrayFunc) {
+ return flatRest(function(iteratees) {
+ iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
+ return baseRest(function(args) {
+ var thisArg = this;
+ return arrayFunc(iteratees, function(iteratee) {
+ return apply(iteratee, thisArg, args);
+ });
+ });
+ });
+ }
+
+ /**
+ * Creates the padding for `string` based on `length`. The `chars` string
+ * is truncated if the number of characters exceeds `length`.
+ *
+ * @private
+ * @param {number} length The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padding for `string`.
+ */
+ function createPadding(length, chars) {
+ chars = chars === undefined ? ' ' : baseToString(chars);
+
+ var charsLength = chars.length;
+ if (charsLength < 2) {
+ return charsLength ? baseRepeat(chars, length) : chars;
+ }
+ var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
+ return hasUnicode(chars)
+ ? castSlice(stringToArray(result), 0, length).join('')
+ : result.slice(0, length);
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with the `this` binding
+ * of `thisArg` and `partials` prepended to the arguments it receives.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} partials The arguments to prepend to those provided to
+ * the new function.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createPartial(func, bitmask, thisArg, partials) {
+ var isBind = bitmask & WRAP_BIND_FLAG,
+ Ctor = createCtor(func);
+
+ function wrapper() {
+ var argsIndex = -1,
+ argsLength = arguments.length,
+ leftIndex = -1,
+ leftLength = partials.length,
+ args = Array(leftLength + argsLength),
+ fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+
+ while (++leftIndex < leftLength) {
+ args[leftIndex] = partials[leftIndex];
+ }
+ while (argsLength--) {
+ args[leftIndex++] = arguments[++argsIndex];
+ }
+ return apply(fn, isBind ? thisArg : this, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a `_.range` or `_.rangeRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new range function.
+ */
+ function createRange(fromRight) {
+ return function(start, end, step) {
+ if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
+ end = step = undefined;
+ }
+ // Ensure the sign of `-0` is preserved.
+ start = toFinite(start);
+ if (end === undefined) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
+ return baseRange(start, end, step, fromRight);
+ };
+ }
+
+ /**
+ * Creates a function that performs a relational operation on two values.
+ *
+ * @private
+ * @param {Function} operator The function to perform the operation.
+ * @returns {Function} Returns the new relational operation function.
+ */
+ function createRelationalOperation(operator) {
+ return function(value, other) {
+ if (!(typeof value == 'string' && typeof other == 'string')) {
+ value = toNumber(value);
+ other = toNumber(other);
+ }
+ return operator(value, other);
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to continue currying.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {Function} wrapFunc The function to create the `func` wrapper.
+ * @param {*} placeholder The placeholder value.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to prepend to those provided to
+ * the new function.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
+ var isCurry = bitmask & WRAP_CURRY_FLAG,
+ newHolders = isCurry ? holders : undefined,
+ newHoldersRight = isCurry ? undefined : holders,
+ newPartials = isCurry ? partials : undefined,
+ newPartialsRight = isCurry ? undefined : partials;
+
+ bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
+ bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
+
+ if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
+ bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
+ }
+ var newData = [
+ func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
+ newHoldersRight, argPos, ary, arity
+ ];
+
+ var result = wrapFunc.apply(undefined, newData);
+ if (isLaziable(func)) {
+ setData(result, newData);
+ }
+ result.placeholder = placeholder;
+ return setWrapToString(result, func, bitmask);
+ }
+
+ /**
+ * Creates a function like `_.round`.
+ *
+ * @private
+ * @param {string} methodName The name of the `Math` method to use when rounding.
+ * @returns {Function} Returns the new round function.
+ */
+ function createRound(methodName) {
+ var func = Math[methodName];
+ return function(number, precision) {
+ number = toNumber(number);
+ precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
+ if (precision) {
+ // Shift with exponential notation to avoid floating-point issues.
+ // See [MDN](https://mdn.io/round#Examples) for more details.
+ var pair = (toString(number) + 'e').split('e'),
+ value = func(pair[0] + 'e' + (+pair[1] + precision));
+
+ pair = (toString(value) + 'e').split('e');
+ return +(pair[0] + 'e' + (+pair[1] - precision));
+ }
+ return func(number);
+ };
+ }
+
+ /**
+ * Creates a set object of `values`.
+ *
+ * @private
+ * @param {Array} values The values to add to the set.
+ * @returns {Object} Returns the new set.
+ */
+ var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
+ return new Set(values);
+ };
+
+ /**
+ * Creates a `_.toPairs` or `_.toPairsIn` function.
+ *
+ * @private
+ * @param {Function} keysFunc The function to get the keys of a given object.
+ * @returns {Function} Returns the new pairs function.
+ */
+ function createToPairs(keysFunc) {
+ return function(object) {
+ var tag = getTag(object);
+ if (tag == mapTag) {
+ return mapToArray(object);
+ }
+ if (tag == setTag) {
+ return setToPairs(object);
+ }
+ return baseToPairs(object, keysFunc(object));
+ };
+ }
+
+ /**
+ * Creates a function that either curries or invokes `func` with optional
+ * `this` binding and partially applied arguments.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to wrap.
+ * @param {number} bitmask The bitmask flags.
+ * 1 - `_.bind`
+ * 2 - `_.bindKey`
+ * 4 - `_.curry` or `_.curryRight` of a bound function
+ * 8 - `_.curry`
+ * 16 - `_.curryRight`
+ * 32 - `_.partial`
+ * 64 - `_.partialRight`
+ * 128 - `_.rearg`
+ * 256 - `_.ary`
+ * 512 - `_.flip`
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to be partially applied.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
+ var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
+ if (!isBindKey && typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var length = partials ? partials.length : 0;
+ if (!length) {
+ bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
+ partials = holders = undefined;
+ }
+ ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
+ arity = arity === undefined ? arity : toInteger(arity);
+ length -= holders ? holders.length : 0;
+
+ if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
+ var partialsRight = partials,
+ holdersRight = holders;
+
+ partials = holders = undefined;
+ }
+ var data = isBindKey ? undefined : getData(func);
+
+ var newData = [
+ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
+ argPos, ary, arity
+ ];
+
+ if (data) {
+ mergeData(newData, data);
+ }
+ func = newData[0];
+ bitmask = newData[1];
+ thisArg = newData[2];
+ partials = newData[3];
+ holders = newData[4];
+ arity = newData[9] = newData[9] === undefined
+ ? (isBindKey ? 0 : func.length)
+ : nativeMax(newData[9] - length, 0);
+
+ if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
+ bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
+ }
+ if (!bitmask || bitmask == WRAP_BIND_FLAG) {
+ var result = createBind(func, bitmask, thisArg);
+ } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
+ result = createCurry(func, bitmask, arity);
+ } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
+ result = createPartial(func, bitmask, thisArg, partials);
+ } else {
+ result = createHybrid.apply(undefined, newData);
+ }
+ var setter = data ? baseSetData : setData;
+ return setWrapToString(setter(result, newData), func, bitmask);
+ }
+
+ /**
+ * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
+ * of source objects to the destination object for all destination properties
+ * that resolve to `undefined`.
+ *
+ * @private
+ * @param {*} objValue The destination value.
+ * @param {*} srcValue The source value.
+ * @param {string} key The key of the property to assign.
+ * @param {Object} object The parent object of `objValue`.
+ * @returns {*} Returns the value to assign.
+ */
+ function customDefaultsAssignIn(objValue, srcValue, key, object) {
+ if (objValue === undefined ||
+ (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
+ return srcValue;
+ }
+ return objValue;
+ }
+
+ /**
+ * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
+ * objects into destination objects that are passed thru.
+ *
+ * @private
+ * @param {*} objValue The destination value.
+ * @param {*} srcValue The source value.
+ * @param {string} key The key of the property to merge.
+ * @param {Object} object The parent object of `objValue`.
+ * @param {Object} source The parent object of `srcValue`.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ * @returns {*} Returns the value to assign.
+ */
+ function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
+ if (isObject(objValue) && isObject(srcValue)) {
+ // Recursively merge objects and arrays (susceptible to call stack limits).
+ stack.set(srcValue, objValue);
+ baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);
+ stack['delete'](srcValue);
+ }
+ return objValue;
+ }
+
+ /**
+ * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
+ * objects.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @param {string} key The key of the property to inspect.
+ * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
+ */
+ function customOmitClone(value) {
+ return isPlainObject(value) ? undefined : value;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for arrays with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Array} array The array to compare.
+ * @param {Array} other The other array to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `array` and `other` objects.
+ * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
+ */
+ function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
+ arrLength = array.length,
+ othLength = other.length;
+
+ if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
+ return false;
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(array);
+ if (stacked && stack.get(other)) {
+ return stacked == other;
+ }
+ var index = -1,
+ result = true,
+ seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
+
+ stack.set(array, other);
+ stack.set(other, array);
+
+ // Ignore non-index properties.
+ while (++index < arrLength) {
+ var arrValue = array[index],
+ othValue = other[index];
+
+ if (customizer) {
+ var compared = isPartial
+ ? customizer(othValue, arrValue, index, other, array, stack)
+ : customizer(arrValue, othValue, index, array, other, stack);
+ }
+ if (compared !== undefined) {
+ if (compared) {
+ continue;
+ }
+ result = false;
+ break;
+ }
+ // Recursively compare arrays (susceptible to call stack limits).
+ if (seen) {
+ if (!arraySome(other, function(othValue, othIndex) {
+ if (!cacheHas(seen, othIndex) &&
+ (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
+ return seen.push(othIndex);
+ }
+ })) {
+ result = false;
+ break;
+ }
+ } else if (!(
+ arrValue === othValue ||
+ equalFunc(arrValue, othValue, bitmask, customizer, stack)
+ )) {
+ result = false;
+ break;
+ }
+ }
+ stack['delete'](array);
+ stack['delete'](other);
+ return result;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for comparing objects of
+ * the same `toStringTag`.
+ *
+ * **Note:** This function only supports comparing values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {string} tag The `toStringTag` of the objects to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
+ switch (tag) {
+ case dataViewTag:
+ if ((object.byteLength != other.byteLength) ||
+ (object.byteOffset != other.byteOffset)) {
+ return false;
+ }
+ object = object.buffer;
+ other = other.buffer;
+
+ case arrayBufferTag:
+ if ((object.byteLength != other.byteLength) ||
+ !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
+ return false;
+ }
+ return true;
+
+ case boolTag:
+ case dateTag:
+ case numberTag:
+ // Coerce booleans to `1` or `0` and dates to milliseconds.
+ // Invalid dates are coerced to `NaN`.
+ return eq(+object, +other);
+
+ case errorTag:
+ return object.name == other.name && object.message == other.message;
+
+ case regexpTag:
+ case stringTag:
+ // Coerce regexes to strings and treat strings, primitives and objects,
+ // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
+ // for more details.
+ return object == (other + '');
+
+ case mapTag:
+ var convert = mapToArray;
+
+ case setTag:
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
+ convert || (convert = setToArray);
+
+ if (object.size != other.size && !isPartial) {
+ return false;
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(object);
+ if (stacked) {
+ return stacked == other;
+ }
+ bitmask |= COMPARE_UNORDERED_FLAG;
+
+ // Recursively compare objects (susceptible to call stack limits).
+ stack.set(object, other);
+ var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
+ stack['delete'](object);
+ return result;
+
+ case symbolTag:
+ if (symbolValueOf) {
+ return symbolValueOf.call(object) == symbolValueOf.call(other);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for objects with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
+ objProps = getAllKeys(object),
+ objLength = objProps.length,
+ othProps = getAllKeys(other),
+ othLength = othProps.length;
+
+ if (objLength != othLength && !isPartial) {
+ return false;
+ }
+ var index = objLength;
+ while (index--) {
+ var key = objProps[index];
+ if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
+ return false;
+ }
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(object);
+ if (stacked && stack.get(other)) {
+ return stacked == other;
+ }
+ var result = true;
+ stack.set(object, other);
+ stack.set(other, object);
+
+ var skipCtor = isPartial;
+ while (++index < objLength) {
+ key = objProps[index];
+ var objValue = object[key],
+ othValue = other[key];
+
+ if (customizer) {
+ var compared = isPartial
+ ? customizer(othValue, objValue, key, other, object, stack)
+ : customizer(objValue, othValue, key, object, other, stack);
+ }
+ // Recursively compare objects (susceptible to call stack limits).
+ if (!(compared === undefined
+ ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
+ : compared
+ )) {
+ result = false;
+ break;
+ }
+ skipCtor || (skipCtor = key == 'constructor');
+ }
+ if (result && !skipCtor) {
+ var objCtor = object.constructor,
+ othCtor = other.constructor;
+
+ // Non `Object` object instances with different constructors are not equal.
+ if (objCtor != othCtor &&
+ ('constructor' in object && 'constructor' in other) &&
+ !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
+ typeof othCtor == 'function' && othCtor instanceof othCtor)) {
+ result = false;
+ }
+ }
+ stack['delete'](object);
+ stack['delete'](other);
+ return result;
+ }
+
+ /**
+ * A specialized version of `baseRest` which flattens the rest array.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @returns {Function} Returns the new function.
+ */
+ function flatRest(func) {
+ return setToString(overRest(func, undefined, flatten), func + '');
+ }
+
+ /**
+ * Creates an array of own enumerable property names and symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+ function getAllKeys(object) {
+ return baseGetAllKeys(object, keys, getSymbols);
+ }
+
+ /**
+ * Creates an array of own and inherited enumerable property names and
+ * symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+ function getAllKeysIn(object) {
+ return baseGetAllKeys(object, keysIn, getSymbolsIn);
+ }
+
+ /**
+ * Gets metadata for `func`.
+ *
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {*} Returns the metadata for `func`.
+ */
+ var getData = !metaMap ? noop : function(func) {
+ return metaMap.get(func);
+ };
+
+ /**
+ * Gets the name of `func`.
+ *
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {string} Returns the function name.
+ */
+ function getFuncName(func) {
+ var result = (func.name + ''),
+ array = realNames[result],
+ length = hasOwnProperty.call(realNames, result) ? array.length : 0;
+
+ while (length--) {
+ var data = array[length],
+ otherFunc = data.func;
+ if (otherFunc == null || otherFunc == func) {
+ return data.name;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gets the argument placeholder value for `func`.
+ *
+ * @private
+ * @param {Function} func The function to inspect.
+ * @returns {*} Returns the placeholder value.
+ */
+ function getHolder(func) {
+ var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
+ return object.placeholder;
+ }
+
+ /**
+ * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
+ * this function returns the custom method, otherwise it returns `baseIteratee`.
+ * If arguments are provided, the chosen function is invoked with them and
+ * its result is returned.
+ *
+ * @private
+ * @param {*} [value] The value to convert to an iteratee.
+ * @param {number} [arity] The arity of the created iteratee.
+ * @returns {Function} Returns the chosen function or its result.
+ */
+ function getIteratee() {
+ var result = lodash.iteratee || iteratee;
+ result = result === iteratee ? baseIteratee : result;
+ return arguments.length ? result(arguments[0], arguments[1]) : result;
+ }
+
+ /**
+ * Gets the data for `map`.
+ *
+ * @private
+ * @param {Object} map The map to query.
+ * @param {string} key The reference key.
+ * @returns {*} Returns the map data.
+ */
+ function getMapData(map, key) {
+ var data = map.__data__;
+ return isKeyable(key)
+ ? data[typeof key == 'string' ? 'string' : 'hash']
+ : data.map;
+ }
+
+ /**
+ * Gets the property names, values, and compare flags of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the match data of `object`.
+ */
+ function getMatchData(object) {
+ var result = keys(object),
+ length = result.length;
+
+ while (length--) {
+ var key = result[length],
+ value = object[key];
+
+ result[length] = [key, value, isStrictComparable(value)];
+ }
+ return result;
+ }
+
+ /**
+ * Gets the native function at `key` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
+ */
+ function getNative(object, key) {
+ var value = getValue(object, key);
+ return baseIsNative(value) ? value : undefined;
+ }
+
+ /**
+ * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the raw `toStringTag`.
+ */
+ function getRawTag(value) {
+ var isOwn = hasOwnProperty.call(value, symToStringTag),
+ tag = value[symToStringTag];
+
+ try {
+ value[symToStringTag] = undefined;
+ var unmasked = true;
+ } catch (e) {}
+
+ var result = nativeObjectToString.call(value);
+ if (unmasked) {
+ if (isOwn) {
+ value[symToStringTag] = tag;
+ } else {
+ delete value[symToStringTag];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array of the own enumerable symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
+ */
+ var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
+ if (object == null) {
+ return [];
+ }
+ object = Object(object);
+ return arrayFilter(nativeGetSymbols(object), function(symbol) {
+ return propertyIsEnumerable.call(object, symbol);
+ });
+ };
+
+ /**
+ * Creates an array of the own and inherited enumerable symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
+ */
+ var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
+ var result = [];
+ while (object) {
+ arrayPush(result, getSymbols(object));
+ object = getPrototype(object);
+ }
+ return result;
+ };
+
+ /**
+ * Gets the `toStringTag` of `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+ var getTag = baseGetTag;
+
+ // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
+ if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
+ (Map && getTag(new Map) != mapTag) ||
+ (Promise && getTag(Promise.resolve()) != promiseTag) ||
+ (Set && getTag(new Set) != setTag) ||
+ (WeakMap && getTag(new WeakMap) != weakMapTag)) {
+ getTag = function(value) {
+ var result = baseGetTag(value),
+ Ctor = result == objectTag ? value.constructor : undefined,
+ ctorString = Ctor ? toSource(Ctor) : '';
+
+ if (ctorString) {
+ switch (ctorString) {
+ case dataViewCtorString: return dataViewTag;
+ case mapCtorString: return mapTag;
+ case promiseCtorString: return promiseTag;
+ case setCtorString: return setTag;
+ case weakMapCtorString: return weakMapTag;
+ }
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Gets the view, applying any `transforms` to the `start` and `end` positions.
+ *
+ * @private
+ * @param {number} start The start of the view.
+ * @param {number} end The end of the view.
+ * @param {Array} transforms The transformations to apply to the view.
+ * @returns {Object} Returns an object containing the `start` and `end`
+ * positions of the view.
+ */
+ function getView(start, end, transforms) {
+ var index = -1,
+ length = transforms.length;
+
+ while (++index < length) {
+ var data = transforms[index],
+ size = data.size;
+
+ switch (data.type) {
+ case 'drop': start += size; break;
+ case 'dropRight': end -= size; break;
+ case 'take': end = nativeMin(end, start + size); break;
+ case 'takeRight': start = nativeMax(start, end - size); break;
+ }
+ }
+ return { 'start': start, 'end': end };
+ }
+
+ /**
+ * Extracts wrapper details from the `source` body comment.
+ *
+ * @private
+ * @param {string} source The source to inspect.
+ * @returns {Array} Returns the wrapper details.
+ */
+ function getWrapDetails(source) {
+ var match = source.match(reWrapDetails);
+ return match ? match[1].split(reSplitDetails) : [];
+ }
+
+ /**
+ * Checks if `path` exists on `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @param {Function} hasFunc The function to check properties.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ */
+ function hasPath(object, path, hasFunc) {
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length,
+ result = false;
+
+ while (++index < length) {
+ var key = toKey(path[index]);
+ if (!(result = object != null && hasFunc(object, key))) {
+ break;
+ }
+ object = object[key];
+ }
+ if (result || ++index != length) {
+ return result;
+ }
+ length = object == null ? 0 : object.length;
+ return !!length && isLength(length) && isIndex(key, length) &&
+ (isArray(object) || isArguments(object));
+ }
+
+ /**
+ * Initializes an array clone.
+ *
+ * @private
+ * @param {Array} array The array to clone.
+ * @returns {Array} Returns the initialized clone.
+ */
+ function initCloneArray(array) {
+ var length = array.length,
+ result = array.constructor(length);
+
+ // Add properties assigned by `RegExp#exec`.
+ if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
+ result.index = array.index;
+ result.input = array.input;
+ }
+ return result;
+ }
+
+ /**
+ * Initializes an object clone.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneObject(object) {
+ return (typeof object.constructor == 'function' && !isPrototype(object))
+ ? baseCreate(getPrototype(object))
+ : {};
+ }
+
+ /**
+ * Initializes an object clone based on its `toStringTag`.
+ *
+ * **Note:** This function only supports cloning values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @param {string} tag The `toStringTag` of the object to clone.
+ * @param {Function} cloneFunc The function to clone values.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneByTag(object, tag, cloneFunc, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return cloneArrayBuffer(object);
+
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
+
+ case dataViewTag:
+ return cloneDataView(object, isDeep);
+
+ case float32Tag: case float64Tag:
+ case int8Tag: case int16Tag: case int32Tag:
+ case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
+ return cloneTypedArray(object, isDeep);
+
+ case mapTag:
+ return cloneMap(object, isDeep, cloneFunc);
+
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+
+ case regexpTag:
+ return cloneRegExp(object);
+
+ case setTag:
+ return cloneSet(object, isDeep, cloneFunc);
+
+ case symbolTag:
+ return cloneSymbol(object);
+ }
+ }
+
+ /**
+ * Inserts wrapper `details` in a comment at the top of the `source` body.
+ *
+ * @private
+ * @param {string} source The source to modify.
+ * @returns {Array} details The details to insert.
+ * @returns {string} Returns the modified source.
+ */
+ function insertWrapDetails(source, details) {
+ var length = details.length;
+ if (!length) {
+ return source;
+ }
+ var lastIndex = length - 1;
+ details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
+ details = details.join(length > 2 ? ', ' : ' ');
+ return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
+ }
+
+ /**
+ * Checks if `value` is a flattenable `arguments` object or array.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
+ */
+ function isFlattenable(value) {
+ return isArray(value) || isArguments(value) ||
+ !!(spreadableSymbol && value && value[spreadableSymbol]);
+ }
+
+ /**
+ * Checks if `value` is a valid array-like index.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+ */
+ function isIndex(value, length) {
+ length = length == null ? MAX_SAFE_INTEGER : length;
+ return !!length &&
+ (typeof value == 'number' || reIsUint.test(value)) &&
+ (value > -1 && value % 1 == 0 && value < length);
+ }
+
+ /**
+ * Checks if the given arguments are from an iteratee call.
+ *
+ * @private
+ * @param {*} value The potential iteratee value argument.
+ * @param {*} index The potential iteratee index or key argument.
+ * @param {*} object The potential iteratee object argument.
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
+ * else `false`.
+ */
+ function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == 'number'
+ ? (isArrayLike(object) && isIndex(index, object.length))
+ : (type == 'string' && index in object)
+ ) {
+ return eq(object[index], value);
+ }
+ return false;
+ }
+
+ /**
+ * Checks if `value` is a property name and not a property path.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
+ */
+ function isKey(value, object) {
+ if (isArray(value)) {
+ return false;
+ }
+ var type = typeof value;
+ if (type == 'number' || type == 'symbol' || type == 'boolean' ||
+ value == null || isSymbol(value)) {
+ return true;
+ }
+ return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
+ (object != null && value in Object(object));
+ }
+
+ /**
+ * Checks if `value` is suitable for use as unique object key.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
+ */
+ function isKeyable(value) {
+ var type = typeof value;
+ return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
+ ? (value !== '__proto__')
+ : (value === null);
+ }
+
+ /**
+ * Checks if `func` has a lazy counterpart.
+ *
+ * @private
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
+ * else `false`.
+ */
+ function isLaziable(func) {
+ var funcName = getFuncName(func),
+ other = lodash[funcName];
+
+ if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
+ return false;
+ }
+ if (func === other) {
+ return true;
+ }
+ var data = getData(other);
+ return !!data && func === data[0];
+ }
+
+ /**
+ * Checks if `func` has its source masked.
+ *
+ * @private
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` is masked, else `false`.
+ */
+ function isMasked(func) {
+ return !!maskSrcKey && (maskSrcKey in func);
+ }
+
+ /**
+ * Checks if `func` is capable of being masked.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
+ */
+ var isMaskable = coreJsData ? isFunction : stubFalse;
+
+ /**
+ * Checks if `value` is likely a prototype object.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
+ */
+ function isPrototype(value) {
+ var Ctor = value && value.constructor,
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
+
+ return value === proto;
+ }
+
+ /**
+ * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` if suitable for strict
+ * equality comparisons, else `false`.
+ */
+ function isStrictComparable(value) {
+ return value === value && !isObject(value);
+ }
+
+ /**
+ * A specialized version of `matchesProperty` for source values suitable
+ * for strict equality comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new spec function.
+ */
+ function matchesStrictComparable(key, srcValue) {
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ return object[key] === srcValue &&
+ (srcValue !== undefined || (key in Object(object)));
+ };
+ }
+
+ /**
+ * A specialized version of `_.memoize` which clears the memoized function's
+ * cache when it exceeds `MAX_MEMOIZE_SIZE`.
+ *
+ * @private
+ * @param {Function} func The function to have its output memoized.
+ * @returns {Function} Returns the new memoized function.
+ */
+ function memoizeCapped(func) {
+ var result = memoize(func, function(key) {
+ if (cache.size === MAX_MEMOIZE_SIZE) {
+ cache.clear();
+ }
+ return key;
+ });
+
+ var cache = result.cache;
+ return result;
+ }
+
+ /**
+ * Merges the function metadata of `source` into `data`.
+ *
+ * Merging metadata reduces the number of wrappers used to invoke a function.
+ * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
+ * may be applied regardless of execution order. Methods like `_.ary` and
+ * `_.rearg` modify function arguments, making the order in which they are
+ * executed important, preventing the merging of metadata. However, we make
+ * an exception for a safe combined case where curried functions have `_.ary`
+ * and or `_.rearg` applied.
+ *
+ * @private
+ * @param {Array} data The destination metadata.
+ * @param {Array} source The source metadata.
+ * @returns {Array} Returns `data`.
+ */
+ function mergeData(data, source) {
+ var bitmask = data[1],
+ srcBitmask = source[1],
+ newBitmask = bitmask | srcBitmask,
+ isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
+
+ var isCombo =
+ ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
+ ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
+ ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
+
+ // Exit early if metadata can't be merged.
+ if (!(isCommon || isCombo)) {
+ return data;
+ }
+ // Use source `thisArg` if available.
+ if (srcBitmask & WRAP_BIND_FLAG) {
+ data[2] = source[2];
+ // Set when currying a bound function.
+ newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
+ }
+ // Compose partial arguments.
+ var value = source[3];
+ if (value) {
+ var partials = data[3];
+ data[3] = partials ? composeArgs(partials, value, source[4]) : value;
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
+ }
+ // Compose partial right arguments.
+ value = source[5];
+ if (value) {
+ partials = data[5];
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
+ }
+ // Use source `argPos` if available.
+ value = source[7];
+ if (value) {
+ data[7] = value;
+ }
+ // Use source `ary` if it's smaller.
+ if (srcBitmask & WRAP_ARY_FLAG) {
+ data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
+ }
+ // Use source `arity` if one is not provided.
+ if (data[9] == null) {
+ data[9] = source[9];
+ }
+ // Use source `func` and merge bitmasks.
+ data[0] = source[0];
+ data[1] = newBitmask;
+
+ return data;
+ }
+
+ /**
+ * This function is like
+ * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * except that it includes inherited enumerable properties.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function nativeKeysIn(object) {
+ var result = [];
+ if (object != null) {
+ for (var key in Object(object)) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Converts `value` to a string using `Object.prototype.toString`.
+ *
+ * @private
+ * @param {*} value The value to convert.
+ * @returns {string} Returns the converted string.
+ */
+ function objectToString(value) {
+ return nativeObjectToString.call(value);
+ }
+
+ /**
+ * A specialized version of `baseRest` which transforms the rest array.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @param {Function} transform The rest array transform.
+ * @returns {Function} Returns the new function.
+ */
+ function overRest(func, start, transform) {
+ start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
+ return function() {
+ var args = arguments,
+ index = -1,
+ length = nativeMax(args.length - start, 0),
+ array = Array(length);
+
+ while (++index < length) {
+ array[index] = args[start + index];
+ }
+ index = -1;
+ var otherArgs = Array(start + 1);
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = transform(array);
+ return apply(func, this, otherArgs);
+ };
+ }
+
+ /**
+ * Gets the parent value at `path` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} path The path to get the parent value of.
+ * @returns {*} Returns the parent value.
+ */
+ function parent(object, path) {
+ return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
+ }
+
+ /**
+ * Reorder `array` according to the specified indexes where the element at
+ * the first index is assigned as the first element, the element at
+ * the second index is assigned as the second element, and so on.
+ *
+ * @private
+ * @param {Array} array The array to reorder.
+ * @param {Array} indexes The arranged array indexes.
+ * @returns {Array} Returns `array`.
+ */
+ function reorder(array, indexes) {
+ var arrLength = array.length,
+ length = nativeMin(indexes.length, arrLength),
+ oldArray = copyArray(array);
+
+ while (length--) {
+ var index = indexes[length];
+ array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
+ }
+ return array;
+ }
+
+ /**
+ * Sets metadata for `func`.
+ *
+ * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
+ * period of time, it will trip its breaker and transition to an identity
+ * function to avoid garbage collection pauses in V8. See
+ * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
+ * for more details.
+ *
+ * @private
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
+ */
+ var setData = shortOut(baseSetData);
+
+ /**
+ * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
+ *
+ * @private
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @returns {number|Object} Returns the timer id or timeout object.
+ */
+ var setTimeout = ctxSetTimeout || function(func, wait) {
+ return root.setTimeout(func, wait);
+ };
+
+ /**
+ * Sets the `toString` method of `func` to return `string`.
+ *
+ * @private
+ * @param {Function} func The function to modify.
+ * @param {Function} string The `toString` result.
+ * @returns {Function} Returns `func`.
+ */
+ var setToString = shortOut(baseSetToString);
+
+ /**
+ * Sets the `toString` method of `wrapper` to mimic the source of `reference`
+ * with wrapper details in a comment at the top of the source body.
+ *
+ * @private
+ * @param {Function} wrapper The function to modify.
+ * @param {Function} reference The reference function.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @returns {Function} Returns `wrapper`.
+ */
+ function setWrapToString(wrapper, reference, bitmask) {
+ var source = (reference + '');
+ return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
+ }
+
+ /**
+ * Creates a function that'll short out and invoke `identity` instead
+ * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
+ * milliseconds.
+ *
+ * @private
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new shortable function.
+ */
+ function shortOut(func) {
+ var count = 0,
+ lastCalled = 0;
+
+ return function() {
+ var stamp = nativeNow(),
+ remaining = HOT_SPAN - (stamp - lastCalled);
+
+ lastCalled = stamp;
+ if (remaining > 0) {
+ if (++count >= HOT_COUNT) {
+ return arguments[0];
+ }
+ } else {
+ count = 0;
+ }
+ return func.apply(undefined, arguments);
+ };
+ }
+
+ /**
+ * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
+ *
+ * @private
+ * @param {Array} array The array to shuffle.
+ * @param {number} [size=array.length] The size of `array`.
+ * @returns {Array} Returns `array`.
+ */
+ function shuffleSelf(array, size) {
+ var index = -1,
+ length = array.length,
+ lastIndex = length - 1;
+
+ size = size === undefined ? length : size;
+ while (++index < size) {
+ var rand = baseRandom(index, lastIndex),
+ value = array[rand];
+
+ array[rand] = array[index];
+ array[index] = value;
+ }
+ array.length = size;
+ return array;
+ }
+
+ /**
+ * Converts `string` to a property path array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the property path array.
+ */
+ var stringToPath = memoizeCapped(function(string) {
+ var result = [];
+ if (reLeadingDot.test(string)) {
+ result.push('');
+ }
+ string.replace(rePropName, function(match, number, quote, string) {
+ result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
+ });
+ return result;
+ });
+
+ /**
+ * Converts `value` to a string key if it's not a string or symbol.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {string|symbol} Returns the key.
+ */
+ function toKey(value) {
+ if (typeof value == 'string' || isSymbol(value)) {
+ return value;
+ }
+ var result = (value + '');
+ return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
+ }
+
+ /**
+ * Converts `func` to its source code.
+ *
+ * @private
+ * @param {Function} func The function to convert.
+ * @returns {string} Returns the source code.
+ */
+ function toSource(func) {
+ if (func != null) {
+ try {
+ return funcToString.call(func);
+ } catch (e) {}
+ try {
+ return (func + '');
+ } catch (e) {}
+ }
+ return '';
+ }
+
+ /**
+ * Updates wrapper `details` based on `bitmask` flags.
+ *
+ * @private
+ * @returns {Array} details The details to modify.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @returns {Array} Returns `details`.
+ */
+ function updateWrapDetails(details, bitmask) {
+ arrayEach(wrapFlags, function(pair) {
+ var value = '_.' + pair[0];
+ if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
+ details.push(value);
+ }
+ });
+ return details.sort();
+ }
+
+ /**
+ * Creates a clone of `wrapper`.
+ *
+ * @private
+ * @param {Object} wrapper The wrapper to clone.
+ * @returns {Object} Returns the cloned wrapper.
+ */
+ function wrapperClone(wrapper) {
+ if (wrapper instanceof LazyWrapper) {
+ return wrapper.clone();
+ }
+ var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
+ result.__actions__ = copyArray(wrapper.__actions__);
+ result.__index__ = wrapper.__index__;
+ result.__values__ = wrapper.__values__;
+ return result;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an array of elements split into groups the length of `size`.
+ * If `array` can't be split evenly, the final chunk will be the remaining
+ * elements.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to process.
+ * @param {number} [size=1] The length of each chunk
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the new array of chunks.
+ * @example
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 2);
+ * // => [['a', 'b'], ['c', 'd']]
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 3);
+ * // => [['a', 'b', 'c'], ['d']]
+ */
+ function chunk(array, size, guard) {
+ if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
+ size = 1;
+ } else {
+ size = nativeMax(toInteger(size), 0);
+ }
+ var length = array == null ? 0 : array.length;
+ if (!length || size < 1) {
+ return [];
+ }
+ var index = 0,
+ resIndex = 0,
+ result = Array(nativeCeil(length / size));
+
+ while (index < length) {
+ result[resIndex++] = baseSlice(array, index, (index += size));
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array with all falsey values removed. The values `false`, `null`,
+ * `0`, `""`, `undefined`, and `NaN` are falsey.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to compact.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.compact([0, 1, false, 2, '', 3]);
+ * // => [1, 2, 3]
+ */
+ function compact(array) {
+ var index = -1,
+ length = array == null ? 0 : array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (value) {
+ result[resIndex++] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates a new array concatenating `array` with any additional arrays
+ * and/or values.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to concatenate.
+ * @param {...*} [values] The values to concatenate.
+ * @returns {Array} Returns the new concatenated array.
+ * @example
+ *
+ * var array = [1];
+ * var other = _.concat(array, 2, [3], [[4]]);
+ *
+ * console.log(other);
+ * // => [1, 2, 3, [4]]
+ *
+ * console.log(array);
+ * // => [1]
+ */
+ function concat() {
+ var length = arguments.length;
+ if (!length) {
+ return [];
+ }
+ var args = Array(length - 1),
+ array = arguments[0],
+ index = length;
+
+ while (index--) {
+ args[index - 1] = arguments[index];
+ }
+ return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
+ }
+
+ /**
+ * Creates an array of `array` values not included in the other given arrays
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons. The order and references of result values are
+ * determined by the first array.
+ *
+ * **Note:** Unlike `_.pullAll`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @see _.without, _.xor
+ * @example
+ *
+ * _.difference([2, 1], [2, 3]);
+ * // => [1]
+ */
+ var difference = baseRest(function(array, values) {
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
+ : [];
+ });
+
+ /**
+ * This method is like `_.difference` except that it accepts `iteratee` which
+ * is invoked for each element of `array` and `values` to generate the criterion
+ * by which they're compared. The order and references of result values are
+ * determined by the first array. The iteratee is invoked with one argument:
+ * (value).
+ *
+ * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
+ * // => [1.2]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
+ * // => [{ 'x': 2 }]
+ */
+ var differenceBy = baseRest(function(array, values) {
+ var iteratee = last(values);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined;
+ }
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
+ : [];
+ });
+
+ /**
+ * This method is like `_.difference` except that it accepts `comparator`
+ * which is invoked to compare elements of `array` to `values`. The order and
+ * references of result values are determined by the first array. The comparator
+ * is invoked with two arguments: (arrVal, othVal).
+ *
+ * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ *
+ * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
+ * // => [{ 'x': 2, 'y': 1 }]
+ */
+ var differenceWith = baseRest(function(array, values) {
+ var comparator = last(values);
+ if (isArrayLikeObject(comparator)) {
+ comparator = undefined;
+ }
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
+ : [];
+ });
+
+ /**
+ * Creates a slice of `array` with `n` elements dropped from the beginning.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.5.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.drop([1, 2, 3]);
+ * // => [2, 3]
+ *
+ * _.drop([1, 2, 3], 2);
+ * // => [3]
+ *
+ * _.drop([1, 2, 3], 5);
+ * // => []
+ *
+ * _.drop([1, 2, 3], 0);
+ * // => [1, 2, 3]
+ */
+ function drop(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined) ? 1 : toInteger(n);
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements dropped from the end.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.dropRight([1, 2, 3]);
+ * // => [1, 2]
+ *
+ * _.dropRight([1, 2, 3], 2);
+ * // => [1]
+ *
+ * _.dropRight([1, 2, 3], 5);
+ * // => []
+ *
+ * _.dropRight([1, 2, 3], 0);
+ * // => [1, 2, 3]
+ */
+ function dropRight(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined) ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` excluding elements dropped from the end.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.dropRightWhile(users, function(o) { return !o.active; });
+ * // => objects for ['barney']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.dropRightWhile(users, ['active', false]);
+ * // => objects for ['barney']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.dropRightWhile(users, 'active');
+ * // => objects for ['barney', 'fred', 'pebbles']
+ */
+ function dropRightWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), true, true)
+ : [];
+ }
+
+ /**
+ * Creates a slice of `array` excluding elements dropped from the beginning.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.dropWhile(users, function(o) { return !o.active; });
+ * // => objects for ['pebbles']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.dropWhile(users, { 'user': 'barney', 'active': false });
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.dropWhile(users, ['active', false]);
+ * // => objects for ['pebbles']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.dropWhile(users, 'active');
+ * // => objects for ['barney', 'fred', 'pebbles']
+ */
+ function dropWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), true)
+ : [];
+ }
+
+ /**
+ * Fills elements of `array` with `value` from `start` up to, but not
+ * including, `end`.
+ *
+ * **Note:** This method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.2.0
+ * @category Array
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _.fill(array, 'a');
+ * console.log(array);
+ * // => ['a', 'a', 'a']
+ *
+ * _.fill(Array(3), 2);
+ * // => [2, 2, 2]
+ *
+ * _.fill([4, 6, 8, 10], '*', 1, 3);
+ * // => [4, '*', '*', 10]
+ */
+ function fill(array, value, start, end) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
+ start = 0;
+ end = length;
+ }
+ return baseFill(array, value, start, end);
+ }
+
+ /**
+ * This method is like `_.find` except that it returns the index of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.findIndex(users, function(o) { return o.user == 'barney'; });
+ * // => 0
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findIndex(users, { 'user': 'fred', 'active': false });
+ * // => 1
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findIndex(users, ['active', false]);
+ * // => 0
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findIndex(users, 'active');
+ * // => 2
+ */
+ function findIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseFindIndex(array, getIteratee(predicate, 3), index);
+ }
+
+ /**
+ * This method is like `_.findIndex` except that it iterates over elements
+ * of `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=array.length-1] The index to search from.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
+ * // => 2
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findLastIndex(users, { 'user': 'barney', 'active': true });
+ * // => 0
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findLastIndex(users, ['active', false]);
+ * // => 2
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findLastIndex(users, 'active');
+ * // => 0
+ */
+ function findLastIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = length - 1;
+ if (fromIndex !== undefined) {
+ index = toInteger(fromIndex);
+ index = fromIndex < 0
+ ? nativeMax(length + index, 0)
+ : nativeMin(index, length - 1);
+ }
+ return baseFindIndex(array, getIteratee(predicate, 3), index, true);
+ }
+
+ /**
+ * Flattens `array` a single level deep.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flatten([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, [3, [4]], 5]
+ */
+ function flatten(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, 1) : [];
+ }
+
+ /**
+ * Recursively flattens `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flattenDeep([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, 3, 4, 5]
+ */
+ function flattenDeep(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, INFINITY) : [];
+ }
+
+ /**
+ * Recursively flatten `array` up to `depth` times.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.4.0
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @param {number} [depth=1] The maximum recursion depth.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * var array = [1, [2, [3, [4]], 5]];
+ *
+ * _.flattenDepth(array, 1);
+ * // => [1, 2, [3, [4]], 5]
+ *
+ * _.flattenDepth(array, 2);
+ * // => [1, 2, 3, [4], 5]
+ */
+ function flattenDepth(array, depth) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ depth = depth === undefined ? 1 : toInteger(depth);
+ return baseFlatten(array, depth);
+ }
+
+ /**
+ * The inverse of `_.toPairs`; this method returns an object composed
+ * from key-value `pairs`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} pairs The key-value pairs.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.fromPairs([['a', 1], ['b', 2]]);
+ * // => { 'a': 1, 'b': 2 }
+ */
+ function fromPairs(pairs) {
+ var index = -1,
+ length = pairs == null ? 0 : pairs.length,
+ result = {};
+
+ while (++index < length) {
+ var pair = pairs[index];
+ result[pair[0]] = pair[1];
+ }
+ return result;
+ }
+
+ /**
+ * Gets the first element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @alias first
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the first element of `array`.
+ * @example
+ *
+ * _.head([1, 2, 3]);
+ * // => 1
+ *
+ * _.head([]);
+ * // => undefined
+ */
+ function head(array) {
+ return (array && array.length) ? array[0] : undefined;
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `value` is found in `array`
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons. If `fromIndex` is negative, it's used as the
+ * offset from the end of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.indexOf([1, 2, 1, 2], 2);
+ * // => 1
+ *
+ * // Search from the `fromIndex`.
+ * _.indexOf([1, 2, 1, 2], 2, 2);
+ * // => 3
+ */
+ function indexOf(array, value, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseIndexOf(array, value, index);
+ }
+
+ /**
+ * Gets all but the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.initial([1, 2, 3]);
+ * // => [1, 2]
+ */
+ function initial(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSlice(array, 0, -1) : [];
+ }
+
+ /**
+ * Creates an array of unique values that are included in all given arrays
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons. The order and references of result values are
+ * determined by the first array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of intersecting values.
+ * @example
+ *
+ * _.intersection([2, 1], [2, 3]);
+ * // => [2]
+ */
+ var intersection = baseRest(function(arrays) {
+ var mapped = arrayMap(arrays, castArrayLikeObject);
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped)
+ : [];
+ });
+
+ /**
+ * This method is like `_.intersection` except that it accepts `iteratee`
+ * which is invoked for each element of each `arrays` to generate the criterion
+ * by which they're compared. The order and references of result values are
+ * determined by the first array. The iteratee is invoked with one argument:
+ * (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of intersecting values.
+ * @example
+ *
+ * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
+ * // => [2.1]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }]
+ */
+ var intersectionBy = baseRest(function(arrays) {
+ var iteratee = last(arrays),
+ mapped = arrayMap(arrays, castArrayLikeObject);
+
+ if (iteratee === last(mapped)) {
+ iteratee = undefined;
+ } else {
+ mapped.pop();
+ }
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped, getIteratee(iteratee, 2))
+ : [];
+ });
+
+ /**
+ * This method is like `_.intersection` except that it accepts `comparator`
+ * which is invoked to compare elements of `arrays`. The order and references
+ * of result values are determined by the first array. The comparator is
+ * invoked with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of intersecting values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.intersectionWith(objects, others, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }]
+ */
+ var intersectionWith = baseRest(function(arrays) {
+ var comparator = last(arrays),
+ mapped = arrayMap(arrays, castArrayLikeObject);
+
+ comparator = typeof comparator == 'function' ? comparator : undefined;
+ if (comparator) {
+ mapped.pop();
+ }
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped, undefined, comparator)
+ : [];
+ });
+
+ /**
+ * Converts all elements in `array` into a string separated by `separator`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to convert.
+ * @param {string} [separator=','] The element separator.
+ * @returns {string} Returns the joined string.
+ * @example
+ *
+ * _.join(['a', 'b', 'c'], '~');
+ * // => 'a~b~c'
+ */
+ function join(array, separator) {
+ return array == null ? '' : nativeJoin.call(array, separator);
+ }
+
+ /**
+ * Gets the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the last element of `array`.
+ * @example
+ *
+ * _.last([1, 2, 3]);
+ * // => 3
+ */
+ function last(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? array[length - 1] : undefined;
+ }
+
+ /**
+ * This method is like `_.indexOf` except that it iterates over elements of
+ * `array` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=array.length-1] The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.lastIndexOf([1, 2, 1, 2], 2);
+ * // => 3
+ *
+ * // Search from the `fromIndex`.
+ * _.lastIndexOf([1, 2, 1, 2], 2, 2);
+ * // => 1
+ */
+ function lastIndexOf(array, value, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = length;
+ if (fromIndex !== undefined) {
+ index = toInteger(fromIndex);
+ index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
+ }
+ return value === value
+ ? strictLastIndexOf(array, value, index)
+ : baseFindIndex(array, baseIsNaN, index, true);
+ }
+
+ /**
+ * Gets the element at index `n` of `array`. If `n` is negative, the nth
+ * element from the end is returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.11.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=0] The index of the element to return.
+ * @returns {*} Returns the nth element of `array`.
+ * @example
+ *
+ * var array = ['a', 'b', 'c', 'd'];
+ *
+ * _.nth(array, 1);
+ * // => 'b'
+ *
+ * _.nth(array, -2);
+ * // => 'c';
+ */
+ function nth(array, n) {
+ return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
+ }
+
+ /**
+ * Removes all given values from `array` using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
+ * to remove elements from an array by predicate.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...*} [values] The values to remove.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
+ *
+ * _.pull(array, 'a', 'c');
+ * console.log(array);
+ * // => ['b', 'b']
+ */
+ var pull = baseRest(pullAll);
+
+ /**
+ * This method is like `_.pull` except that it accepts an array of values to remove.
+ *
+ * **Note:** Unlike `_.difference`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
+ *
+ * _.pullAll(array, ['a', 'c']);
+ * console.log(array);
+ * // => ['b', 'b']
+ */
+ function pullAll(array, values) {
+ return (array && array.length && values && values.length)
+ ? basePullAll(array, values)
+ : array;
+ }
+
+ /**
+ * This method is like `_.pullAll` except that it accepts `iteratee` which is
+ * invoked for each element of `array` and `values` to generate the criterion
+ * by which they're compared. The iteratee is invoked with one argument: (value).
+ *
+ * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
+ *
+ * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
+ * console.log(array);
+ * // => [{ 'x': 2 }]
+ */
+ function pullAllBy(array, values, iteratee) {
+ return (array && array.length && values && values.length)
+ ? basePullAll(array, values, getIteratee(iteratee, 2))
+ : array;
+ }
+
+ /**
+ * This method is like `_.pullAll` except that it accepts `comparator` which
+ * is invoked to compare elements of `array` to `values`. The comparator is
+ * invoked with two arguments: (arrVal, othVal).
+ *
+ * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.6.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
+ *
+ * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
+ * console.log(array);
+ * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
+ */
+ function pullAllWith(array, values, comparator) {
+ return (array && array.length && values && values.length)
+ ? basePullAll(array, values, undefined, comparator)
+ : array;
+ }
+
+ /**
+ * Removes elements from `array` corresponding to `indexes` and returns an
+ * array of removed elements.
+ *
+ * **Note:** Unlike `_.at`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...(number|number[])} [indexes] The indexes of elements to remove.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = ['a', 'b', 'c', 'd'];
+ * var pulled = _.pullAt(array, [1, 3]);
+ *
+ * console.log(array);
+ * // => ['a', 'c']
+ *
+ * console.log(pulled);
+ * // => ['b', 'd']
+ */
+ var pullAt = flatRest(function(array, indexes) {
+ var length = array == null ? 0 : array.length,
+ result = baseAt(array, indexes);
+
+ basePullAt(array, arrayMap(indexes, function(index) {
+ return isIndex(index, length) ? +index : index;
+ }).sort(compareAscending));
+
+ return result;
+ });
+
+ /**
+ * Removes all elements from `array` that `predicate` returns truthy for
+ * and returns an array of the removed elements. The predicate is invoked
+ * with three arguments: (value, index, array).
+ *
+ * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
+ * to pull elements from an array by value.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = [1, 2, 3, 4];
+ * var evens = _.remove(array, function(n) {
+ * return n % 2 == 0;
+ * });
+ *
+ * console.log(array);
+ * // => [1, 3]
+ *
+ * console.log(evens);
+ * // => [2, 4]
+ */
+ function remove(array, predicate) {
+ var result = [];
+ if (!(array && array.length)) {
+ return result;
+ }
+ var index = -1,
+ indexes = [],
+ length = array.length;
+
+ predicate = getIteratee(predicate, 3);
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result.push(value);
+ indexes.push(index);
+ }
+ }
+ basePullAt(array, indexes);
+ return result;
+ }
+
+ /**
+ * Reverses `array` so that the first element becomes the last, the second
+ * element becomes the second to last, and so on.
+ *
+ * **Note:** This method mutates `array` and is based on
+ * [`Array#reverse`](https://mdn.io/Array/reverse).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _.reverse(array);
+ * // => [3, 2, 1]
+ *
+ * console.log(array);
+ * // => [3, 2, 1]
+ */
+ function reverse(array) {
+ return array == null ? array : nativeReverse.call(array);
+ }
+
+ /**
+ * Creates a slice of `array` from `start` up to, but not including, `end`.
+ *
+ * **Note:** This method is used instead of
+ * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
+ * returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function slice(array, start, end) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
+ start = 0;
+ end = length;
+ }
+ else {
+ start = start == null ? 0 : toInteger(start);
+ end = end === undefined ? length : toInteger(end);
+ }
+ return baseSlice(array, start, end);
+ }
+
+ /**
+ * Uses a binary search to determine the lowest index at which `value`
+ * should be inserted into `array` in order to maintain its sort order.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedIndex([30, 50], 40);
+ * // => 1
+ */
+ function sortedIndex(array, value) {
+ return baseSortedIndex(array, value);
+ }
+
+ /**
+ * This method is like `_.sortedIndex` except that it accepts `iteratee`
+ * which is invoked for `value` and each element of `array` to compute their
+ * sort ranking. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * var objects = [{ 'x': 4 }, { 'x': 5 }];
+ *
+ * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
+ * // => 0
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
+ * // => 0
+ */
+ function sortedIndexBy(array, value, iteratee) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
+ }
+
+ /**
+ * This method is like `_.indexOf` except that it performs a binary
+ * search on a sorted `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
+ * // => 1
+ */
+ function sortedIndexOf(array, value) {
+ var length = array == null ? 0 : array.length;
+ if (length) {
+ var index = baseSortedIndex(array, value);
+ if (index < length && eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * This method is like `_.sortedIndex` except that it returns the highest
+ * index at which `value` should be inserted into `array` in order to
+ * maintain its sort order.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
+ * // => 4
+ */
+ function sortedLastIndex(array, value) {
+ return baseSortedIndex(array, value, true);
+ }
+
+ /**
+ * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
+ * which is invoked for `value` and each element of `array` to compute their
+ * sort ranking. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * var objects = [{ 'x': 4 }, { 'x': 5 }];
+ *
+ * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
+ * // => 1
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
+ * // => 1
+ */
+ function sortedLastIndexBy(array, value, iteratee) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
+ }
+
+ /**
+ * This method is like `_.lastIndexOf` except that it performs a binary
+ * search on a sorted `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
+ * // => 3
+ */
+ function sortedLastIndexOf(array, value) {
+ var length = array == null ? 0 : array.length;
+ if (length) {
+ var index = baseSortedIndex(array, value, true) - 1;
+ if (eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * This method is like `_.uniq` except that it's designed and optimized
+ * for sorted arrays.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.sortedUniq([1, 1, 2]);
+ * // => [1, 2]
+ */
+ function sortedUniq(array) {
+ return (array && array.length)
+ ? baseSortedUniq(array)
+ : [];
+ }
+
+ /**
+ * This method is like `_.uniqBy` except that it's designed and optimized
+ * for sorted arrays.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
+ * // => [1.1, 2.3]
+ */
+ function sortedUniqBy(array, iteratee) {
+ return (array && array.length)
+ ? baseSortedUniq(array, getIteratee(iteratee, 2))
+ : [];
+ }
+
+ /**
+ * Gets all but the first element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.tail([1, 2, 3]);
+ * // => [2, 3]
+ */
+ function tail(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSlice(array, 1, length) : [];
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements taken from the beginning.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.take([1, 2, 3]);
+ * // => [1]
+ *
+ * _.take([1, 2, 3], 2);
+ * // => [1, 2]
+ *
+ * _.take([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.take([1, 2, 3], 0);
+ * // => []
+ */
+ function take(array, n, guard) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ n = (guard || n === undefined) ? 1 : toInteger(n);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements taken from the end.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeRight([1, 2, 3]);
+ * // => [3]
+ *
+ * _.takeRight([1, 2, 3], 2);
+ * // => [2, 3]
+ *
+ * _.takeRight([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.takeRight([1, 2, 3], 0);
+ * // => []
+ */
+ function takeRight(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined) ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+
+ /**
+ * Creates a slice of `array` with elements taken from the end. Elements are
+ * taken until `predicate` returns falsey. The predicate is invoked with
+ * three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.takeRightWhile(users, function(o) { return !o.active; });
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
+ * // => objects for ['pebbles']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.takeRightWhile(users, ['active', false]);
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.takeRightWhile(users, 'active');
+ * // => []
+ */
+ function takeRightWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), false, true)
+ : [];
+ }
+
+ /**
+ * Creates a slice of `array` with elements taken from the beginning. Elements
+ * are taken until `predicate` returns falsey. The predicate is invoked with
+ * three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.takeWhile(users, function(o) { return !o.active; });
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.takeWhile(users, { 'user': 'barney', 'active': false });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.takeWhile(users, ['active', false]);
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.takeWhile(users, 'active');
+ * // => []
+ */
+ function takeWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3))
+ : [];
+ }
+
+ /**
+ * Creates an array of unique values, in order, from all given arrays using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.union([2], [1, 2]);
+ * // => [2, 1]
+ */
+ var union = baseRest(function(arrays) {
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
+ });
+
+ /**
+ * This method is like `_.union` except that it accepts `iteratee` which is
+ * invoked for each element of each `arrays` to generate the criterion by
+ * which uniqueness is computed. Result values are chosen from the first
+ * array in which the value occurs. The iteratee is invoked with one argument:
+ * (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.unionBy([2.1], [1.2, 2.3], Math.floor);
+ * // => [2.1, 1.2]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
+ */
+ var unionBy = baseRest(function(arrays) {
+ var iteratee = last(arrays);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined;
+ }
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
+ });
+
+ /**
+ * This method is like `_.union` except that it accepts `comparator` which
+ * is invoked to compare elements of `arrays`. Result values are chosen from
+ * the first array in which the value occurs. The comparator is invoked
+ * with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.unionWith(objects, others, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
+ */
+ var unionWith = baseRest(function(arrays) {
+ var comparator = last(arrays);
+ comparator = typeof comparator == 'function' ? comparator : undefined;
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
+ });
+
+ /**
+ * Creates a duplicate-free version of an array, using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons, in which only the first occurrence of each element
+ * is kept. The order of result values is determined by the order they occur
+ * in the array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.uniq([2, 1, 2]);
+ * // => [2, 1]
+ */
+ function uniq(array) {
+ return (array && array.length) ? baseUniq(array) : [];
+ }
+
+ /**
+ * This method is like `_.uniq` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the criterion by which
+ * uniqueness is computed. The order of result values is determined by the
+ * order they occur in the array. The iteratee is invoked with one argument:
+ * (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
+ * // => [2.1, 1.2]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
+ */
+ function uniqBy(array, iteratee) {
+ return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
+ }
+
+ /**
+ * This method is like `_.uniq` except that it accepts `comparator` which
+ * is invoked to compare elements of `array`. The order of result values is
+ * determined by the order they occur in the array.The comparator is invoked
+ * with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.uniqWith(objects, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
+ */
+ function uniqWith(array, comparator) {
+ comparator = typeof comparator == 'function' ? comparator : undefined;
+ return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
+ }
+
+ /**
+ * This method is like `_.zip` except that it accepts an array of grouped
+ * elements and creates an array regrouping the elements to their pre-zip
+ * configuration.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.2.0
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
+ * // => [['a', 1, true], ['b', 2, false]]
+ *
+ * _.unzip(zipped);
+ * // => [['a', 'b'], [1, 2], [true, false]]
+ */
+ function unzip(array) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var length = 0;
+ array = arrayFilter(array, function(group) {
+ if (isArrayLikeObject(group)) {
+ length = nativeMax(group.length, length);
+ return true;
+ }
+ });
+ return baseTimes(length, function(index) {
+ return arrayMap(array, baseProperty(index));
+ });
+ }
+
+ /**
+ * This method is like `_.unzip` except that it accepts `iteratee` to specify
+ * how regrouped values should be combined. The iteratee is invoked with the
+ * elements of each group: (...group).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.8.0
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @param {Function} [iteratee=_.identity] The function to combine
+ * regrouped values.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
+ * // => [[1, 10, 100], [2, 20, 200]]
+ *
+ * _.unzipWith(zipped, _.add);
+ * // => [3, 30, 300]
+ */
+ function unzipWith(array, iteratee) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var result = unzip(array);
+ if (iteratee == null) {
+ return result;
+ }
+ return arrayMap(result, function(group) {
+ return apply(iteratee, undefined, group);
+ });
+ }
+
+ /**
+ * Creates an array excluding all given values using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * **Note:** Unlike `_.pull`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...*} [values] The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @see _.difference, _.xor
+ * @example
+ *
+ * _.without([2, 1, 2, 3], 1, 2);
+ * // => [3]
+ */
+ var without = baseRest(function(array, values) {
+ return isArrayLikeObject(array)
+ ? baseDifference(array, values)
+ : [];
+ });
+
+ /**
+ * Creates an array of unique values that is the
+ * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
+ * of the given arrays. The order of result values is determined by the order
+ * they occur in the arrays.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of filtered values.
+ * @see _.difference, _.without
+ * @example
+ *
+ * _.xor([2, 1], [2, 3]);
+ * // => [1, 3]
+ */
+ var xor = baseRest(function(arrays) {
+ return baseXor(arrayFilter(arrays, isArrayLikeObject));
+ });
+
+ /**
+ * This method is like `_.xor` except that it accepts `iteratee` which is
+ * invoked for each element of each `arrays` to generate the criterion by
+ * which by which they're compared. The order of result values is determined
+ * by the order they occur in the arrays. The iteratee is invoked with one
+ * argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
+ * // => [1.2, 3.4]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 2 }]
+ */
+ var xorBy = baseRest(function(arrays) {
+ var iteratee = last(arrays);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined;
+ }
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
+ });
+
+ /**
+ * This method is like `_.xor` except that it accepts `comparator` which is
+ * invoked to compare elements of `arrays`. The order of result values is
+ * determined by the order they occur in the arrays. The comparator is invoked
+ * with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.xorWith(objects, others, _.isEqual);
+ * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
+ */
+ var xorWith = baseRest(function(arrays) {
+ var comparator = last(arrays);
+ comparator = typeof comparator == 'function' ? comparator : undefined;
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
+ });
+
+ /**
+ * Creates an array of grouped elements, the first of which contains the
+ * first elements of the given arrays, the second of which contains the
+ * second elements of the given arrays, and so on.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zip(['a', 'b'], [1, 2], [true, false]);
+ * // => [['a', 1, true], ['b', 2, false]]
+ */
+ var zip = baseRest(unzip);
+
+ /**
+ * This method is like `_.fromPairs` except that it accepts two arrays,
+ * one of property identifiers and one of corresponding values.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.4.0
+ * @category Array
+ * @param {Array} [props=[]] The property identifiers.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObject(['a', 'b'], [1, 2]);
+ * // => { 'a': 1, 'b': 2 }
+ */
+ function zipObject(props, values) {
+ return baseZipObject(props || [], values || [], assignValue);
+ }
+
+ /**
+ * This method is like `_.zipObject` except that it supports property paths.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.1.0
+ * @category Array
+ * @param {Array} [props=[]] The property identifiers.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
+ * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
+ */
+ function zipObjectDeep(props, values) {
+ return baseZipObject(props || [], values || [], baseSet);
+ }
+
+ /**
+ * This method is like `_.zip` except that it accepts `iteratee` to specify
+ * how grouped values should be combined. The iteratee is invoked with the
+ * elements of each group: (...group).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.8.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @param {Function} [iteratee=_.identity] The function to combine
+ * grouped values.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
+ * return a + b + c;
+ * });
+ * // => [111, 222]
+ */
+ var zipWith = baseRest(function(arrays) {
+ var length = arrays.length,
+ iteratee = length > 1 ? arrays[length - 1] : undefined;
+
+ iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
+ return unzipWith(arrays, iteratee);
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a `lodash` wrapper instance that wraps `value` with explicit method
+ * chain sequences enabled. The result of such sequences must be unwrapped
+ * with `_#value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.3.0
+ * @category Seq
+ * @param {*} value The value to wrap.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'pebbles', 'age': 1 }
+ * ];
+ *
+ * var youngest = _
+ * .chain(users)
+ * .sortBy('age')
+ * .map(function(o) {
+ * return o.user + ' is ' + o.age;
+ * })
+ * .head()
+ * .value();
+ * // => 'pebbles is 1'
+ */
+ function chain(value) {
+ var result = lodash(value);
+ result.__chain__ = true;
+ return result;
+ }
+
+ /**
+ * This method invokes `interceptor` and returns `value`. The interceptor
+ * is invoked with one argument; (value). The purpose of this method is to
+ * "tap into" a method chain sequence in order to modify intermediate results.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Seq
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * _([1, 2, 3])
+ * .tap(function(array) {
+ * // Mutate input array.
+ * array.pop();
+ * })
+ * .reverse()
+ * .value();
+ * // => [2, 1]
+ */
+ function tap(value, interceptor) {
+ interceptor(value);
+ return value;
+ }
+
+ /**
+ * This method is like `_.tap` except that it returns the result of `interceptor`.
+ * The purpose of this method is to "pass thru" values replacing intermediate
+ * results in a method chain sequence.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Seq
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @returns {*} Returns the result of `interceptor`.
+ * @example
+ *
+ * _(' abc ')
+ * .chain()
+ * .trim()
+ * .thru(function(value) {
+ * return [value];
+ * })
+ * .value();
+ * // => ['abc']
+ */
+ function thru(value, interceptor) {
+ return interceptor(value);
+ }
+
+ /**
+ * This method is the wrapper version of `_.at`.
+ *
+ * @name at
+ * @memberOf _
+ * @since 1.0.0
+ * @category Seq
+ * @param {...(string|string[])} [paths] The property paths to pick.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
+ *
+ * _(object).at(['a[0].b.c', 'a[1]']).value();
+ * // => [3, 4]
+ */
+ var wrapperAt = flatRest(function(paths) {
+ var length = paths.length,
+ start = length ? paths[0] : 0,
+ value = this.__wrapped__,
+ interceptor = function(object) { return baseAt(object, paths); };
+
+ if (length > 1 || this.__actions__.length ||
+ !(value instanceof LazyWrapper) || !isIndex(start)) {
+ return this.thru(interceptor);
+ }
+ value = value.slice(start, +start + (length ? 1 : 0));
+ value.__actions__.push({
+ 'func': thru,
+ 'args': [interceptor],
+ 'thisArg': undefined
+ });
+ return new LodashWrapper(value, this.__chain__).thru(function(array) {
+ if (length && !array.length) {
+ array.push(undefined);
+ }
+ return array;
+ });
+ });
+
+ /**
+ * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
+ *
+ * @name chain
+ * @memberOf _
+ * @since 0.1.0
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * // A sequence without explicit chaining.
+ * _(users).head();
+ * // => { 'user': 'barney', 'age': 36 }
+ *
+ * // A sequence with explicit chaining.
+ * _(users)
+ * .chain()
+ * .head()
+ * .pick('user')
+ * .value();
+ * // => { 'user': 'barney' }
+ */
+ function wrapperChain() {
+ return chain(this);
+ }
+
+ /**
+ * Executes the chain sequence and returns the wrapped result.
+ *
+ * @name commit
+ * @memberOf _
+ * @since 3.2.0
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2];
+ * var wrapped = _(array).push(3);
+ *
+ * console.log(array);
+ * // => [1, 2]
+ *
+ * wrapped = wrapped.commit();
+ * console.log(array);
+ * // => [1, 2, 3]
+ *
+ * wrapped.last();
+ * // => 3
+ *
+ * console.log(array);
+ * // => [1, 2, 3]
+ */
+ function wrapperCommit() {
+ return new LodashWrapper(this.value(), this.__chain__);
+ }
+
+ /**
+ * Gets the next value on a wrapped object following the
+ * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
+ *
+ * @name next
+ * @memberOf _
+ * @since 4.0.0
+ * @category Seq
+ * @returns {Object} Returns the next iterator value.
+ * @example
+ *
+ * var wrapped = _([1, 2]);
+ *
+ * wrapped.next();
+ * // => { 'done': false, 'value': 1 }
+ *
+ * wrapped.next();
+ * // => { 'done': false, 'value': 2 }
+ *
+ * wrapped.next();
+ * // => { 'done': true, 'value': undefined }
+ */
+ function wrapperNext() {
+ if (this.__values__ === undefined) {
+ this.__values__ = toArray(this.value());
+ }
+ var done = this.__index__ >= this.__values__.length,
+ value = done ? undefined : this.__values__[this.__index__++];
+
+ return { 'done': done, 'value': value };
+ }
+
+ /**
+ * Enables the wrapper to be iterable.
+ *
+ * @name Symbol.iterator
+ * @memberOf _
+ * @since 4.0.0
+ * @category Seq
+ * @returns {Object} Returns the wrapper object.
+ * @example
+ *
+ * var wrapped = _([1, 2]);
+ *
+ * wrapped[Symbol.iterator]() === wrapped;
+ * // => true
+ *
+ * Array.from(wrapped);
+ * // => [1, 2]
+ */
+ function wrapperToIterator() {
+ return this;
+ }
+
+ /**
+ * Creates a clone of the chain sequence planting `value` as the wrapped value.
+ *
+ * @name plant
+ * @memberOf _
+ * @since 3.2.0
+ * @category Seq
+ * @param {*} value The value to plant.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var wrapped = _([1, 2]).map(square);
+ * var other = wrapped.plant([3, 4]);
+ *
+ * other.value();
+ * // => [9, 16]
+ *
+ * wrapped.value();
+ * // => [1, 4]
+ */
+ function wrapperPlant(value) {
+ var result,
+ parent = this;
+
+ while (parent instanceof baseLodash) {
+ var clone = wrapperClone(parent);
+ clone.__index__ = 0;
+ clone.__values__ = undefined;
+ if (result) {
+ previous.__wrapped__ = clone;
+ } else {
+ result = clone;
+ }
+ var previous = clone;
+ parent = parent.__wrapped__;
+ }
+ previous.__wrapped__ = value;
+ return result;
+ }
+
+ /**
+ * This method is the wrapper version of `_.reverse`.
+ *
+ * **Note:** This method mutates the wrapped array.
+ *
+ * @name reverse
+ * @memberOf _
+ * @since 0.1.0
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _(array).reverse().value()
+ * // => [3, 2, 1]
+ *
+ * console.log(array);
+ * // => [3, 2, 1]
+ */
+ function wrapperReverse() {
+ var value = this.__wrapped__;
+ if (value instanceof LazyWrapper) {
+ var wrapped = value;
+ if (this.__actions__.length) {
+ wrapped = new LazyWrapper(this);
+ }
+ wrapped = wrapped.reverse();
+ wrapped.__actions__.push({
+ 'func': thru,
+ 'args': [reverse],
+ 'thisArg': undefined
+ });
+ return new LodashWrapper(wrapped, this.__chain__);
+ }
+ return this.thru(reverse);
+ }
+
+ /**
+ * Executes the chain sequence to resolve the unwrapped value.
+ *
+ * @name value
+ * @memberOf _
+ * @since 0.1.0
+ * @alias toJSON, valueOf
+ * @category Seq
+ * @returns {*} Returns the resolved unwrapped value.
+ * @example
+ *
+ * _([1, 2, 3]).value();
+ * // => [1, 2, 3]
+ */
+ function wrapperValue() {
+ return baseWrapperValue(this.__wrapped__, this.__actions__);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` thru `iteratee`. The corresponding value of
+ * each key is the number of times the key was returned by `iteratee`. The
+ * iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.5.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.countBy([6.1, 4.2, 6.3], Math.floor);
+ * // => { '4': 1, '6': 2 }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.countBy(['one', 'two', 'three'], 'length');
+ * // => { '3': 2, '5': 1 }
+ */
+ var countBy = createAggregator(function(result, value, key) {
+ if (hasOwnProperty.call(result, key)) {
+ ++result[key];
+ } else {
+ baseAssignValue(result, key, 1);
+ }
+ });
+
+ /**
+ * Checks if `predicate` returns truthy for **all** elements of `collection`.
+ * Iteration is stopped once `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index|key, collection).
+ *
+ * **Note:** This method returns `true` for
+ * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
+ * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
+ * elements of empty collections.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ * @example
+ *
+ * _.every([true, 1, null, 'yes'], Boolean);
+ * // => false
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.every(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.every(users, ['active', false]);
+ * // => true
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.every(users, 'active');
+ * // => false
+ */
+ function every(collection, predicate, guard) {
+ var func = isArray(collection) ? arrayEvery : baseEvery;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Iterates over elements of `collection`, returning an array of all elements
+ * `predicate` returns truthy for. The predicate is invoked with three
+ * arguments: (value, index|key, collection).
+ *
+ * **Note:** Unlike `_.remove`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ * @see _.reject
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * _.filter(users, function(o) { return !o.active; });
+ * // => objects for ['fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.filter(users, { 'age': 36, 'active': true });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.filter(users, ['active', false]);
+ * // => objects for ['fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.filter(users, 'active');
+ * // => objects for ['barney']
+ */
+ function filter(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Iterates over elements of `collection`, returning the first element
+ * `predicate` returns truthy for. The predicate is invoked with three
+ * arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false },
+ * { 'user': 'pebbles', 'age': 1, 'active': true }
+ * ];
+ *
+ * _.find(users, function(o) { return o.age < 40; });
+ * // => object for 'barney'
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.find(users, { 'age': 1, 'active': true });
+ * // => object for 'pebbles'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.find(users, ['active', false]);
+ * // => object for 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.find(users, 'active');
+ * // => object for 'barney'
+ */
+ var find = createFind(findIndex);
+
+ /**
+ * This method is like `_.find` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=collection.length-1] The index to search from.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * _.findLast([1, 2, 3, 4], function(n) {
+ * return n % 2 == 1;
+ * });
+ * // => 3
+ */
+ var findLast = createFind(findLastIndex);
+
+ /**
+ * Creates a flattened array of values by running each element in `collection`
+ * thru `iteratee` and flattening the mapped results. The iteratee is invoked
+ * with three arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [n, n];
+ * }
+ *
+ * _.flatMap([1, 2], duplicate);
+ * // => [1, 1, 2, 2]
+ */
+ function flatMap(collection, iteratee) {
+ return baseFlatten(map(collection, iteratee), 1);
+ }
+
+ /**
+ * This method is like `_.flatMap` except that it recursively flattens the
+ * mapped results.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.7.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [[[n, n]]];
+ * }
+ *
+ * _.flatMapDeep([1, 2], duplicate);
+ * // => [1, 1, 2, 2]
+ */
+ function flatMapDeep(collection, iteratee) {
+ return baseFlatten(map(collection, iteratee), INFINITY);
+ }
+
+ /**
+ * This method is like `_.flatMap` except that it recursively flattens the
+ * mapped results up to `depth` times.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.7.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {number} [depth=1] The maximum recursion depth.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [[[n, n]]];
+ * }
+ *
+ * _.flatMapDepth([1, 2], duplicate, 2);
+ * // => [[1, 1], [2, 2]]
+ */
+ function flatMapDepth(collection, iteratee, depth) {
+ depth = depth === undefined ? 1 : toInteger(depth);
+ return baseFlatten(map(collection, iteratee), depth);
+ }
+
+ /**
+ * Iterates over elements of `collection` and invokes `iteratee` for each element.
+ * The iteratee is invoked with three arguments: (value, index|key, collection).
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * **Note:** As with other "Collections" methods, objects with a "length"
+ * property are iterated like arrays. To avoid this behavior use `_.forIn`
+ * or `_.forOwn` for object iteration.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @alias each
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ * @see _.forEachRight
+ * @example
+ *
+ * _.forEach([1, 2], function(value) {
+ * console.log(value);
+ * });
+ * // => Logs `1` then `2`.
+ *
+ * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'a' then 'b' (iteration order is not guaranteed).
+ */
+ function forEach(collection, iteratee) {
+ var func = isArray(collection) ? arrayEach : baseEach;
+ return func(collection, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * This method is like `_.forEach` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @alias eachRight
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ * @see _.forEach
+ * @example
+ *
+ * _.forEachRight([1, 2], function(value) {
+ * console.log(value);
+ * });
+ * // => Logs `2` then `1`.
+ */
+ function forEachRight(collection, iteratee) {
+ var func = isArray(collection) ? arrayEachRight : baseEachRight;
+ return func(collection, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` thru `iteratee`. The order of grouped values
+ * is determined by the order they occur in `collection`. The corresponding
+ * value of each key is an array of elements responsible for generating the
+ * key. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.groupBy([6.1, 4.2, 6.3], Math.floor);
+ * // => { '4': [4.2], '6': [6.1, 6.3] }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.groupBy(['one', 'two', 'three'], 'length');
+ * // => { '3': ['one', 'two'], '5': ['three'] }
+ */
+ var groupBy = createAggregator(function(result, value, key) {
+ if (hasOwnProperty.call(result, key)) {
+ result[key].push(value);
+ } else {
+ baseAssignValue(result, key, [value]);
+ }
+ });
+
+ /**
+ * Checks if `value` is in `collection`. If `collection` is a string, it's
+ * checked for a substring of `value`, otherwise
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * is used for equality comparisons. If `fromIndex` is negative, it's used as
+ * the offset from the end of `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
+ * @returns {boolean} Returns `true` if `value` is found, else `false`.
+ * @example
+ *
+ * _.includes([1, 2, 3], 1);
+ * // => true
+ *
+ * _.includes([1, 2, 3], 1, 2);
+ * // => false
+ *
+ * _.includes({ 'a': 1, 'b': 2 }, 1);
+ * // => true
+ *
+ * _.includes('abcd', 'bc');
+ * // => true
+ */
+ function includes(collection, value, fromIndex, guard) {
+ collection = isArrayLike(collection) ? collection : values(collection);
+ fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
+
+ var length = collection.length;
+ if (fromIndex < 0) {
+ fromIndex = nativeMax(length + fromIndex, 0);
+ }
+ return isString(collection)
+ ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
+ : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
+ }
+
+ /**
+ * Invokes the method at `path` of each element in `collection`, returning
+ * an array of the results of each invoked method. Any additional arguments
+ * are provided to each invoked method. If `path` is a function, it's invoked
+ * for, and `this` bound to, each element in `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Array|Function|string} path The path of the method to invoke or
+ * the function invoked per iteration.
+ * @param {...*} [args] The arguments to invoke each method with.
+ * @returns {Array} Returns the array of results.
+ * @example
+ *
+ * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
+ * // => [[1, 5, 7], [1, 2, 3]]
+ *
+ * _.invokeMap([123, 456], String.prototype.split, '');
+ * // => [['1', '2', '3'], ['4', '5', '6']]
+ */
+ var invokeMap = baseRest(function(collection, path, args) {
+ var index = -1,
+ isFunc = typeof path == 'function',
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value) {
+ result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
+ });
+ return result;
+ });
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` thru `iteratee`. The corresponding value of
+ * each key is the last element responsible for generating the key. The
+ * iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * var array = [
+ * { 'dir': 'left', 'code': 97 },
+ * { 'dir': 'right', 'code': 100 }
+ * ];
+ *
+ * _.keyBy(array, function(o) {
+ * return String.fromCharCode(o.code);
+ * });
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+ *
+ * _.keyBy(array, 'dir');
+ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+ */
+ var keyBy = createAggregator(function(result, value, key) {
+ baseAssignValue(result, key, value);
+ });
+
+ /**
+ * Creates an array of values by running each element in `collection` thru
+ * `iteratee`. The iteratee is invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
+ *
+ * The guarded methods are:
+ * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
+ * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
+ * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
+ * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * _.map([4, 8], square);
+ * // => [16, 64]
+ *
+ * _.map({ 'a': 4, 'b': 8 }, square);
+ * // => [16, 64] (iteration order is not guaranteed)
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.map(users, 'user');
+ * // => ['barney', 'fred']
+ */
+ function map(collection, iteratee) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ return func(collection, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * This method is like `_.sortBy` except that it allows specifying the sort
+ * orders of the iteratees to sort by. If `orders` is unspecified, all values
+ * are sorted in ascending order. Otherwise, specify an order of "desc" for
+ * descending or "asc" for ascending sort order of corresponding values.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
+ * The iteratees to sort by.
+ * @param {string[]} [orders] The sort orders of `iteratees`.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 34 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'barney', 'age': 36 }
+ * ];
+ *
+ * // Sort by `user` in ascending order and by `age` in descending order.
+ * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
+ * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
+ */
+ function orderBy(collection, iteratees, orders, guard) {
+ if (collection == null) {
+ return [];
+ }
+ if (!isArray(iteratees)) {
+ iteratees = iteratees == null ? [] : [iteratees];
+ }
+ orders = guard ? undefined : orders;
+ if (!isArray(orders)) {
+ orders = orders == null ? [] : [orders];
+ }
+ return baseOrderBy(collection, iteratees, orders);
+ }
+
+ /**
+ * Creates an array of elements split into two groups, the first of which
+ * contains elements `predicate` returns truthy for, the second of which
+ * contains elements `predicate` returns falsey for. The predicate is
+ * invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the array of grouped elements.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true },
+ * { 'user': 'pebbles', 'age': 1, 'active': false }
+ * ];
+ *
+ * _.partition(users, function(o) { return o.active; });
+ * // => objects for [['fred'], ['barney', 'pebbles']]
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.partition(users, { 'age': 1, 'active': false });
+ * // => objects for [['pebbles'], ['barney', 'fred']]
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.partition(users, ['active', false]);
+ * // => objects for [['barney', 'pebbles'], ['fred']]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.partition(users, 'active');
+ * // => objects for [['fred'], ['barney', 'pebbles']]
+ */
+ var partition = createAggregator(function(result, value, key) {
+ result[key ? 0 : 1].push(value);
+ }, function() { return [[], []]; });
+
+ /**
+ * Reduces `collection` to a value which is the accumulated result of running
+ * each element in `collection` thru `iteratee`, where each successive
+ * invocation is supplied the return value of the previous. If `accumulator`
+ * is not given, the first element of `collection` is used as the initial
+ * value. The iteratee is invoked with four arguments:
+ * (accumulator, value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.reduce`, `_.reduceRight`, and `_.transform`.
+ *
+ * The guarded methods are:
+ * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
+ * and `sortBy`
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @returns {*} Returns the accumulated value.
+ * @see _.reduceRight
+ * @example
+ *
+ * _.reduce([1, 2], function(sum, n) {
+ * return sum + n;
+ * }, 0);
+ * // => 3
+ *
+ * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
+ * (result[value] || (result[value] = [])).push(key);
+ * return result;
+ * }, {});
+ * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
+ */
+ function reduce(collection, iteratee, accumulator) {
+ var func = isArray(collection) ? arrayReduce : baseReduce,
+ initAccum = arguments.length < 3;
+
+ return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
+ }
+
+ /**
+ * This method is like `_.reduce` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @returns {*} Returns the accumulated value.
+ * @see _.reduce
+ * @example
+ *
+ * var array = [[0, 1], [2, 3], [4, 5]];
+ *
+ * _.reduceRight(array, function(flattened, other) {
+ * return flattened.concat(other);
+ * }, []);
+ * // => [4, 5, 2, 3, 0, 1]
+ */
+ function reduceRight(collection, iteratee, accumulator) {
+ var func = isArray(collection) ? arrayReduceRight : baseReduce,
+ initAccum = arguments.length < 3;
+
+ return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
+ }
+
+ /**
+ * The opposite of `_.filter`; this method returns the elements of `collection`
+ * that `predicate` does **not** return truthy for.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ * @see _.filter
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true }
+ * ];
+ *
+ * _.reject(users, function(o) { return !o.active; });
+ * // => objects for ['fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.reject(users, { 'age': 40, 'active': true });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.reject(users, ['active', false]);
+ * // => objects for ['fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.reject(users, 'active');
+ * // => objects for ['barney']
+ */
+ function reject(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, negate(getIteratee(predicate, 3)));
+ }
+
+ /**
+ * Gets a random element from `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to sample.
+ * @returns {*} Returns the random element.
+ * @example
+ *
+ * _.sample([1, 2, 3, 4]);
+ * // => 2
+ */
+ function sample(collection) {
+ var func = isArray(collection) ? arraySample : baseSample;
+ return func(collection);
+ }
+
+ /**
+ * Gets `n` random elements at unique keys from `collection` up to the
+ * size of `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to sample.
+ * @param {number} [n=1] The number of elements to sample.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the random elements.
+ * @example
+ *
+ * _.sampleSize([1, 2, 3], 2);
+ * // => [3, 1]
+ *
+ * _.sampleSize([1, 2, 3], 4);
+ * // => [2, 3, 1]
+ */
+ function sampleSize(collection, n, guard) {
+ if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
+ n = 1;
+ } else {
+ n = toInteger(n);
+ }
+ var func = isArray(collection) ? arraySampleSize : baseSampleSize;
+ return func(collection, n);
+ }
+
+ /**
+ * Creates an array of shuffled values, using a version of the
+ * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ * @example
+ *
+ * _.shuffle([1, 2, 3, 4]);
+ * // => [4, 1, 3, 2]
+ */
+ function shuffle(collection) {
+ var func = isArray(collection) ? arrayShuffle : baseShuffle;
+ return func(collection);
+ }
+
+ /**
+ * Gets the size of `collection` by returning its length for array-like
+ * values or the number of own enumerable string keyed properties for objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to inspect.
+ * @returns {number} Returns the collection size.
+ * @example
+ *
+ * _.size([1, 2, 3]);
+ * // => 3
+ *
+ * _.size({ 'a': 1, 'b': 2 });
+ * // => 2
+ *
+ * _.size('pebbles');
+ * // => 7
+ */
+ function size(collection) {
+ if (collection == null) {
+ return 0;
+ }
+ if (isArrayLike(collection)) {
+ return isString(collection) ? stringSize(collection) : collection.length;
+ }
+ var tag = getTag(collection);
+ if (tag == mapTag || tag == setTag) {
+ return collection.size;
+ }
+ return baseKeys(collection).length;
+ }
+
+ /**
+ * Checks if `predicate` returns truthy for **any** element of `collection`.
+ * Iteration is stopped once `predicate` returns truthy. The predicate is
+ * invoked with three arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ * @example
+ *
+ * _.some([null, 0, 'yes', false], Boolean);
+ * // => true
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false }
+ * ];
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.some(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.some(users, ['active', false]);
+ * // => true
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.some(users, 'active');
+ * // => true
+ */
+ function some(collection, predicate, guard) {
+ var func = isArray(collection) ? arraySome : baseSome;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Creates an array of elements, sorted in ascending order by the results of
+ * running each element in a collection thru each iteratee. This method
+ * performs a stable sort, that is, it preserves the original sort order of
+ * equal elements. The iteratees are invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {...(Function|Function[])} [iteratees=[_.identity]]
+ * The iteratees to sort by.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'barney', 'age': 34 }
+ * ];
+ *
+ * _.sortBy(users, [function(o) { return o.user; }]);
+ * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
+ *
+ * _.sortBy(users, ['user', 'age']);
+ * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
+ */
+ var sortBy = baseRest(function(collection, iteratees) {
+ if (collection == null) {
+ return [];
+ }
+ var length = iteratees.length;
+ if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
+ iteratees = [];
+ } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
+ iteratees = [iteratees[0]];
+ }
+ return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Gets the timestamp of the number of milliseconds that have elapsed since
+ * the Unix epoch (1 January 1970 00:00:00 UTC).
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Date
+ * @returns {number} Returns the timestamp.
+ * @example
+ *
+ * _.defer(function(stamp) {
+ * console.log(_.now() - stamp);
+ * }, _.now());
+ * // => Logs the number of milliseconds it took for the deferred invocation.
+ */
+ var now = ctxNow || function() {
+ return root.Date.now();
+ };
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The opposite of `_.before`; this method creates a function that invokes
+ * `func` once it's called `n` or more times.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {number} n The number of calls before `func` is invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var saves = ['profile', 'settings'];
+ *
+ * var done = _.after(saves.length, function() {
+ * console.log('done saving!');
+ * });
+ *
+ * _.forEach(saves, function(type) {
+ * asyncSave({ 'type': type, 'complete': done });
+ * });
+ * // => Logs 'done saving!' after the two async saves have completed.
+ */
+ function after(n, func) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+
+ /**
+ * Creates a function that invokes `func`, with up to `n` arguments,
+ * ignoring any additional arguments.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {Function} func The function to cap arguments for.
+ * @param {number} [n=func.length] The arity cap.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Function} Returns the new capped function.
+ * @example
+ *
+ * _.map(['6', '8', '10'], _.ary(parseInt, 1));
+ * // => [6, 8, 10]
+ */
+ function ary(func, n, guard) {
+ n = guard ? undefined : n;
+ n = (func && n == null) ? func.length : n;
+ return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
+ }
+
+ /**
+ * Creates a function that invokes `func`, with the `this` binding and arguments
+ * of the created function, while it's called less than `n` times. Subsequent
+ * calls to the created function return the result of the last `func` invocation.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {number} n The number of calls at which `func` is no longer invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * jQuery(element).on('click', _.before(5, addContactToList));
+ * // => Allows adding up to 4 contacts to the list.
+ */
+ function before(n, func) {
+ var result;
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n > 0) {
+ result = func.apply(this, arguments);
+ }
+ if (n <= 1) {
+ func = undefined;
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of `thisArg`
+ * and `partials` prepended to the arguments it receives.
+ *
+ * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
+ * property of bound functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * function greet(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * }
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * var bound = _.bind(greet, object, 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * // Bound with placeholders.
+ * var bound = _.bind(greet, object, _, '!');
+ * bound('hi');
+ * // => 'hi fred!'
+ */
+ var bind = baseRest(function(func, thisArg, partials) {
+ var bitmask = WRAP_BIND_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getHolder(bind));
+ bitmask |= WRAP_PARTIAL_FLAG;
+ }
+ return createWrap(func, bitmask, thisArg, partials, holders);
+ });
+
+ /**
+ * Creates a function that invokes the method at `object[key]` with `partials`
+ * prepended to the arguments it receives.
+ *
+ * This method differs from `_.bind` by allowing bound functions to reference
+ * methods that may be redefined or don't yet exist. See
+ * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
+ * for more details.
+ *
+ * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.10.0
+ * @category Function
+ * @param {Object} object The object to invoke the method on.
+ * @param {string} key The key of the method.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var object = {
+ * 'user': 'fred',
+ * 'greet': function(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * }
+ * };
+ *
+ * var bound = _.bindKey(object, 'greet', 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * object.greet = function(greeting, punctuation) {
+ * return greeting + 'ya ' + this.user + punctuation;
+ * };
+ *
+ * bound('!');
+ * // => 'hiya fred!'
+ *
+ * // Bound with placeholders.
+ * var bound = _.bindKey(object, 'greet', _, '!');
+ * bound('hi');
+ * // => 'hiya fred!'
+ */
+ var bindKey = baseRest(function(object, key, partials) {
+ var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getHolder(bindKey));
+ bitmask |= WRAP_PARTIAL_FLAG;
+ }
+ return createWrap(key, bitmask, object, partials, holders);
+ });
+
+ /**
+ * Creates a function that accepts arguments of `func` and either invokes
+ * `func` returning its result, if at least `arity` number of arguments have
+ * been provided, or returns a function that accepts the remaining `func`
+ * arguments, and so on. The arity of `func` may be specified if `func.length`
+ * is not sufficient.
+ *
+ * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of curried functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Function} Returns the new curried function.
+ * @example
+ *
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
+ *
+ * var curried = _.curry(abc);
+ *
+ * curried(1)(2)(3);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2)(3);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
+ *
+ * // Curried with placeholders.
+ * curried(1)(_, 3)(2);
+ * // => [1, 2, 3]
+ */
+ function curry(func, arity, guard) {
+ arity = guard ? undefined : arity;
+ var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
+ result.placeholder = curry.placeholder;
+ return result;
+ }
+
+ /**
+ * This method is like `_.curry` except that arguments are applied to `func`
+ * in the manner of `_.partialRight` instead of `_.partial`.
+ *
+ * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of curried functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Function} Returns the new curried function.
+ * @example
+ *
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
+ *
+ * var curried = _.curryRight(abc);
+ *
+ * curried(3)(2)(1);
+ * // => [1, 2, 3]
+ *
+ * curried(2, 3)(1);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
+ *
+ * // Curried with placeholders.
+ * curried(3)(1, _)(2);
+ * // => [1, 2, 3]
+ */
+ function curryRight(func, arity, guard) {
+ arity = guard ? undefined : arity;
+ var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
+ result.placeholder = curryRight.placeholder;
+ return result;
+ }
+
+ /**
+ * Creates a debounced function that delays invoking `func` until after `wait`
+ * milliseconds have elapsed since the last time the debounced function was
+ * invoked. The debounced function comes with a `cancel` method to cancel
+ * delayed `func` invocations and a `flush` method to immediately invoke them.
+ * Provide `options` to indicate whether `func` should be invoked on the
+ * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
+ * with the last arguments provided to the debounced function. Subsequent
+ * calls to the debounced function return the result of the last `func`
+ * invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
+ * invoked on the trailing edge of the timeout only if the debounced function
+ * is invoked more than once during the `wait` timeout.
+ *
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
+ * until to the next tick, similar to `setTimeout` with a timeout of `0`.
+ *
+ * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
+ * for details over the differences between `_.debounce` and `_.throttle`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to debounce.
+ * @param {number} [wait=0] The number of milliseconds to delay.
+ * @param {Object} [options={}] The options object.
+ * @param {boolean} [options.leading=false]
+ * Specify invoking on the leading edge of the timeout.
+ * @param {number} [options.maxWait]
+ * The maximum time `func` is allowed to be delayed before it's invoked.
+ * @param {boolean} [options.trailing=true]
+ * Specify invoking on the trailing edge of the timeout.
+ * @returns {Function} Returns the new debounced function.
+ * @example
+ *
+ * // Avoid costly calculations while the window size is in flux.
+ * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
+ *
+ * // Invoke `sendMail` when clicked, debouncing subsequent calls.
+ * jQuery(element).on('click', _.debounce(sendMail, 300, {
+ * 'leading': true,
+ * 'trailing': false
+ * }));
+ *
+ * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
+ * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
+ * var source = new EventSource('/stream');
+ * jQuery(source).on('message', debounced);
+ *
+ * // Cancel the trailing debounced invocation.
+ * jQuery(window).on('popstate', debounced.cancel);
+ */
+ function debounce(func, wait, options) {
+ var lastArgs,
+ lastThis,
+ maxWait,
+ result,
+ timerId,
+ lastCallTime,
+ lastInvokeTime = 0,
+ leading = false,
+ maxing = false,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ wait = toNumber(wait) || 0;
+ if (isObject(options)) {
+ leading = !!options.leading;
+ maxing = 'maxWait' in options;
+ maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+
+ function invokeFunc(time) {
+ var args = lastArgs,
+ thisArg = lastThis;
+
+ lastArgs = lastThis = undefined;
+ lastInvokeTime = time;
+ result = func.apply(thisArg, args);
+ return result;
+ }
+
+ function leadingEdge(time) {
+ // Reset any `maxWait` timer.
+ lastInvokeTime = time;
+ // Start the timer for the trailing edge.
+ timerId = setTimeout(timerExpired, wait);
+ // Invoke the leading edge.
+ return leading ? invokeFunc(time) : result;
+ }
+
+ function remainingWait(time) {
+ var timeSinceLastCall = time - lastCallTime,
+ timeSinceLastInvoke = time - lastInvokeTime,
+ result = wait - timeSinceLastCall;
+
+ return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
+ }
+
+ function shouldInvoke(time) {
+ var timeSinceLastCall = time - lastCallTime,
+ timeSinceLastInvoke = time - lastInvokeTime;
+
+ // Either this is the first call, activity has stopped and we're at the
+ // trailing edge, the system time has gone backwards and we're treating
+ // it as the trailing edge, or we've hit the `maxWait` limit.
+ return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
+ (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
+ }
+
+ function timerExpired() {
+ var time = now();
+ if (shouldInvoke(time)) {
+ return trailingEdge(time);
+ }
+ // Restart the timer.
+ timerId = setTimeout(timerExpired, remainingWait(time));
+ }
+
+ function trailingEdge(time) {
+ timerId = undefined;
+
+ // Only invoke if we have `lastArgs` which means `func` has been
+ // debounced at least once.
+ if (trailing && lastArgs) {
+ return invokeFunc(time);
+ }
+ lastArgs = lastThis = undefined;
+ return result;
+ }
+
+ function cancel() {
+ if (timerId !== undefined) {
+ clearTimeout(timerId);
+ }
+ lastInvokeTime = 0;
+ lastArgs = lastCallTime = lastThis = timerId = undefined;
+ }
+
+ function flush() {
+ return timerId === undefined ? result : trailingEdge(now());
+ }
+
+ function debounced() {
+ var time = now(),
+ isInvoking = shouldInvoke(time);
+
+ lastArgs = arguments;
+ lastThis = this;
+ lastCallTime = time;
+
+ if (isInvoking) {
+ if (timerId === undefined) {
+ return leadingEdge(lastCallTime);
+ }
+ if (maxing) {
+ // Handle invocations in a tight loop.
+ timerId = setTimeout(timerExpired, wait);
+ return invokeFunc(lastCallTime);
+ }
+ }
+ if (timerId === undefined) {
+ timerId = setTimeout(timerExpired, wait);
+ }
+ return result;
+ }
+ debounced.cancel = cancel;
+ debounced.flush = flush;
+ return debounced;
+ }
+
+ /**
+ * Defers invoking the `func` until the current call stack has cleared. Any
+ * additional arguments are provided to `func` when it's invoked.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to defer.
+ * @param {...*} [args] The arguments to invoke `func` with.
+ * @returns {number} Returns the timer id.
+ * @example
+ *
+ * _.defer(function(text) {
+ * console.log(text);
+ * }, 'deferred');
+ * // => Logs 'deferred' after one millisecond.
+ */
+ var defer = baseRest(function(func, args) {
+ return baseDelay(func, 1, args);
+ });
+
+ /**
+ * Invokes `func` after `wait` milliseconds. Any additional arguments are
+ * provided to `func` when it's invoked.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {...*} [args] The arguments to invoke `func` with.
+ * @returns {number} Returns the timer id.
+ * @example
+ *
+ * _.delay(function(text) {
+ * console.log(text);
+ * }, 1000, 'later');
+ * // => Logs 'later' after one second.
+ */
+ var delay = baseRest(function(func, wait, args) {
+ return baseDelay(func, toNumber(wait) || 0, args);
+ });
+
+ /**
+ * Creates a function that invokes `func` with arguments reversed.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Function
+ * @param {Function} func The function to flip arguments for.
+ * @returns {Function} Returns the new flipped function.
+ * @example
+ *
+ * var flipped = _.flip(function() {
+ * return _.toArray(arguments);
+ * });
+ *
+ * flipped('a', 'b', 'c', 'd');
+ * // => ['d', 'c', 'b', 'a']
+ */
+ function flip(func) {
+ return createWrap(func, WRAP_FLIP_FLAG);
+ }
+
+ /**
+ * Creates a function that memoizes the result of `func`. If `resolver` is
+ * provided, it determines the cache key for storing the result based on the
+ * arguments provided to the memoized function. By default, the first argument
+ * provided to the memoized function is used as the map cache key. The `func`
+ * is invoked with the `this` binding of the memoized function.
+ *
+ * **Note:** The cache is exposed as the `cache` property on the memoized
+ * function. Its creation may be customized by replacing the `_.memoize.Cache`
+ * constructor with one whose instances implement the
+ * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
+ * method interface of `clear`, `delete`, `get`, `has`, and `set`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to have its output memoized.
+ * @param {Function} [resolver] The function to resolve the cache key.
+ * @returns {Function} Returns the new memoized function.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2 };
+ * var other = { 'c': 3, 'd': 4 };
+ *
+ * var values = _.memoize(_.values);
+ * values(object);
+ * // => [1, 2]
+ *
+ * values(other);
+ * // => [3, 4]
+ *
+ * object.a = 2;
+ * values(object);
+ * // => [1, 2]
+ *
+ * // Modify the result cache.
+ * values.cache.set(object, ['a', 'b']);
+ * values(object);
+ * // => ['a', 'b']
+ *
+ * // Replace `_.memoize.Cache`.
+ * _.memoize.Cache = WeakMap;
+ */
+ function memoize(func, resolver) {
+ if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var memoized = function() {
+ var args = arguments,
+ key = resolver ? resolver.apply(this, args) : args[0],
+ cache = memoized.cache;
+
+ if (cache.has(key)) {
+ return cache.get(key);
+ }
+ var result = func.apply(this, args);
+ memoized.cache = cache.set(key, result) || cache;
+ return result;
+ };
+ memoized.cache = new (memoize.Cache || MapCache);
+ return memoized;
+ }
+
+ // Expose `MapCache`.
+ memoize.Cache = MapCache;
+
+ /**
+ * Creates a function that negates the result of the predicate `func`. The
+ * `func` predicate is invoked with the `this` binding and arguments of the
+ * created function.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {Function} predicate The predicate to negate.
+ * @returns {Function} Returns the new negated function.
+ * @example
+ *
+ * function isEven(n) {
+ * return n % 2 == 0;
+ * }
+ *
+ * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
+ * // => [1, 3, 5]
+ */
+ function negate(predicate) {
+ if (typeof predicate != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return function() {
+ var args = arguments;
+ switch (args.length) {
+ case 0: return !predicate.call(this);
+ case 1: return !predicate.call(this, args[0]);
+ case 2: return !predicate.call(this, args[0], args[1]);
+ case 3: return !predicate.call(this, args[0], args[1], args[2]);
+ }
+ return !predicate.apply(this, args);
+ };
+ }
+
+ /**
+ * Creates a function that is restricted to invoking `func` once. Repeat calls
+ * to the function return the value of the first invocation. The `func` is
+ * invoked with the `this` binding and arguments of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var initialize = _.once(createApplication);
+ * initialize();
+ * initialize();
+ * // => `createApplication` is invoked once
+ */
+ function once(func) {
+ return before(2, func);
+ }
+
+ /**
+ * Creates a function that invokes `func` with its arguments transformed.
+ *
+ * @static
+ * @since 4.0.0
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to wrap.
+ * @param {...(Function|Function[])} [transforms=[_.identity]]
+ * The argument transforms.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function doubled(n) {
+ * return n * 2;
+ * }
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var func = _.overArgs(function(x, y) {
+ * return [x, y];
+ * }, [square, doubled]);
+ *
+ * func(9, 3);
+ * // => [81, 6]
+ *
+ * func(10, 5);
+ * // => [100, 10]
+ */
+ var overArgs = castRest(function(func, transforms) {
+ transforms = (transforms.length == 1 && isArray(transforms[0]))
+ ? arrayMap(transforms[0], baseUnary(getIteratee()))
+ : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
+
+ var funcsLength = transforms.length;
+ return baseRest(function(args) {
+ var index = -1,
+ length = nativeMin(args.length, funcsLength);
+
+ while (++index < length) {
+ args[index] = transforms[index].call(this, args[index]);
+ }
+ return apply(func, this, args);
+ });
+ });
+
+ /**
+ * Creates a function that invokes `func` with `partials` prepended to the
+ * arguments it receives. This method is like `_.bind` except it does **not**
+ * alter the `this` binding.
+ *
+ * The `_.partial.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of partially
+ * applied functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.2.0
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * function greet(greeting, name) {
+ * return greeting + ' ' + name;
+ * }
+ *
+ * var sayHelloTo = _.partial(greet, 'hello');
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ *
+ * // Partially applied with placeholders.
+ * var greetFred = _.partial(greet, _, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
+ */
+ var partial = baseRest(function(func, partials) {
+ var holders = replaceHolders(partials, getHolder(partial));
+ return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
+ });
+
+ /**
+ * This method is like `_.partial` except that partially applied arguments
+ * are appended to the arguments it receives.
+ *
+ * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of partially
+ * applied functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.0.0
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * function greet(greeting, name) {
+ * return greeting + ' ' + name;
+ * }
+ *
+ * var greetFred = _.partialRight(greet, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
+ *
+ * // Partially applied with placeholders.
+ * var sayHelloTo = _.partialRight(greet, 'hello', _);
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ */
+ var partialRight = baseRest(function(func, partials) {
+ var holders = replaceHolders(partials, getHolder(partialRight));
+ return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
+ });
+
+ /**
+ * Creates a function that invokes `func` with arguments arranged according
+ * to the specified `indexes` where the argument value at the first index is
+ * provided as the first argument, the argument value at the second index is
+ * provided as the second argument, and so on.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {Function} func The function to rearrange arguments for.
+ * @param {...(number|number[])} indexes The arranged argument indexes.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var rearged = _.rearg(function(a, b, c) {
+ * return [a, b, c];
+ * }, [2, 0, 1]);
+ *
+ * rearged('b', 'c', 'a')
+ * // => ['a', 'b', 'c']
+ */
+ var rearg = flatRest(function(func, indexes) {
+ return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
+ });
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of the
+ * created function and arguments from `start` and beyond provided as
+ * an array.
+ *
+ * **Note:** This method is based on the
+ * [rest parameter](https://mdn.io/rest_parameters).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Function
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var say = _.rest(function(what, names) {
+ * return what + ' ' + _.initial(names).join(', ') +
+ * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
+ * });
+ *
+ * say('hello', 'fred', 'barney', 'pebbles');
+ * // => 'hello fred, barney, & pebbles'
+ */
+ function rest(func, start) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ start = start === undefined ? start : toInteger(start);
+ return baseRest(func, start);
+ }
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of the
+ * create function and an array of arguments much like
+ * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
+ *
+ * **Note:** This method is based on the
+ * [spread operator](https://mdn.io/spread_operator).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.2.0
+ * @category Function
+ * @param {Function} func The function to spread arguments over.
+ * @param {number} [start=0] The start position of the spread.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var say = _.spread(function(who, what) {
+ * return who + ' says ' + what;
+ * });
+ *
+ * say(['fred', 'hello']);
+ * // => 'fred says hello'
+ *
+ * var numbers = Promise.all([
+ * Promise.resolve(40),
+ * Promise.resolve(36)
+ * ]);
+ *
+ * numbers.then(_.spread(function(x, y) {
+ * return x + y;
+ * }));
+ * // => a Promise of 76
+ */
+ function spread(func, start) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ start = start == null ? 0 : nativeMax(toInteger(start), 0);
+ return baseRest(function(args) {
+ var array = args[start],
+ otherArgs = castSlice(args, 0, start);
+
+ if (array) {
+ arrayPush(otherArgs, array);
+ }
+ return apply(func, this, otherArgs);
+ });
+ }
+
+ /**
+ * Creates a throttled function that only invokes `func` at most once per
+ * every `wait` milliseconds. The throttled function comes with a `cancel`
+ * method to cancel delayed `func` invocations and a `flush` method to
+ * immediately invoke them. Provide `options` to indicate whether `func`
+ * should be invoked on the leading and/or trailing edge of the `wait`
+ * timeout. The `func` is invoked with the last arguments provided to the
+ * throttled function. Subsequent calls to the throttled function return the
+ * result of the last `func` invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
+ * invoked on the trailing edge of the timeout only if the throttled function
+ * is invoked more than once during the `wait` timeout.
+ *
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
+ * until to the next tick, similar to `setTimeout` with a timeout of `0`.
+ *
+ * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
+ * for details over the differences between `_.throttle` and `_.debounce`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to throttle.
+ * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
+ * @param {Object} [options={}] The options object.
+ * @param {boolean} [options.leading=true]
+ * Specify invoking on the leading edge of the timeout.
+ * @param {boolean} [options.trailing=true]
+ * Specify invoking on the trailing edge of the timeout.
+ * @returns {Function} Returns the new throttled function.
+ * @example
+ *
+ * // Avoid excessively updating the position while scrolling.
+ * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
+ *
+ * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
+ * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
+ * jQuery(element).on('click', throttled);
+ *
+ * // Cancel the trailing throttled invocation.
+ * jQuery(window).on('popstate', throttled.cancel);
+ */
+ function throttle(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (isObject(options)) {
+ leading = 'leading' in options ? !!options.leading : leading;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+ return debounce(func, wait, {
+ 'leading': leading,
+ 'maxWait': wait,
+ 'trailing': trailing
+ });
+ }
+
+ /**
+ * Creates a function that accepts up to one argument, ignoring any
+ * additional arguments.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Function
+ * @param {Function} func The function to cap arguments for.
+ * @returns {Function} Returns the new capped function.
+ * @example
+ *
+ * _.map(['6', '8', '10'], _.unary(parseInt));
+ * // => [6, 8, 10]
+ */
+ function unary(func) {
+ return ary(func, 1);
+ }
+
+ /**
+ * Creates a function that provides `value` to `wrapper` as its first
+ * argument. Any additional arguments provided to the function are appended
+ * to those provided to the `wrapper`. The wrapper is invoked with the `this`
+ * binding of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {*} value The value to wrap.
+ * @param {Function} [wrapper=identity] The wrapper function.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var p = _.wrap(_.escape, function(func, text) {
+ * return '<p>' + func(text) + '</p>';
+ * });
+ *
+ * p('fred, barney, & pebbles');
+ * // => '<p>fred, barney, &amp; pebbles</p>'
+ */
+ function wrap(value, wrapper) {
+ return partial(castFunction(wrapper), value);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Casts `value` as an array if it's not one.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.4.0
+ * @category Lang
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the cast array.
+ * @example
+ *
+ * _.castArray(1);
+ * // => [1]
+ *
+ * _.castArray({ 'a': 1 });
+ * // => [{ 'a': 1 }]
+ *
+ * _.castArray('abc');
+ * // => ['abc']
+ *
+ * _.castArray(null);
+ * // => [null]
+ *
+ * _.castArray(undefined);
+ * // => [undefined]
+ *
+ * _.castArray();
+ * // => []
+ *
+ * var array = [1, 2, 3];
+ * console.log(_.castArray(array) === array);
+ * // => true
+ */
+ function castArray() {
+ if (!arguments.length) {
+ return [];
+ }
+ var value = arguments[0];
+ return isArray(value) ? value : [value];
+ }
+
+ /**
+ * Creates a shallow clone of `value`.
+ *
+ * **Note:** This method is loosely based on the
+ * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
+ * and supports cloning arrays, array buffers, booleans, date objects, maps,
+ * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
+ * arrays. The own enumerable properties of `arguments` objects are cloned
+ * as plain objects. An empty object is returned for uncloneable values such
+ * as error objects, functions, DOM nodes, and WeakMaps.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @returns {*} Returns the cloned value.
+ * @see _.cloneDeep
+ * @example
+ *
+ * var objects = [{ 'a': 1 }, { 'b': 2 }];
+ *
+ * var shallow = _.clone(objects);
+ * console.log(shallow[0] === objects[0]);
+ * // => true
+ */
+ function clone(value) {
+ return baseClone(value, CLONE_SYMBOLS_FLAG);
+ }
+
+ /**
+ * This method is like `_.clone` except that it accepts `customizer` which
+ * is invoked to produce the cloned value. If `customizer` returns `undefined`,
+ * cloning is handled by the method instead. The `customizer` is invoked with
+ * up to four arguments; (value [, index|key, object, stack]).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @param {Function} [customizer] The function to customize cloning.
+ * @returns {*} Returns the cloned value.
+ * @see _.cloneDeepWith
+ * @example
+ *
+ * function customizer(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(false);
+ * }
+ * }
+ *
+ * var el = _.cloneWith(document.body, customizer);
+ *
+ * console.log(el === document.body);
+ * // => false
+ * console.log(el.nodeName);
+ * // => 'BODY'
+ * console.log(el.childNodes.length);
+ * // => 0
+ */
+ function cloneWith(value, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
+ }
+
+ /**
+ * This method is like `_.clone` except that it recursively clones `value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.0.0
+ * @category Lang
+ * @param {*} value The value to recursively clone.
+ * @returns {*} Returns the deep cloned value.
+ * @see _.clone
+ * @example
+ *
+ * var objects = [{ 'a': 1 }, { 'b': 2 }];
+ *
+ * var deep = _.cloneDeep(objects);
+ * console.log(deep[0] === objects[0]);
+ * // => false
+ */
+ function cloneDeep(value) {
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
+ }
+
+ /**
+ * This method is like `_.cloneWith` except that it recursively clones `value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to recursively clone.
+ * @param {Function} [customizer] The function to customize cloning.
+ * @returns {*} Returns the deep cloned value.
+ * @see _.cloneWith
+ * @example
+ *
+ * function customizer(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(true);
+ * }
+ * }
+ *
+ * var el = _.cloneDeepWith(document.body, customizer);
+ *
+ * console.log(el === document.body);
+ * // => false
+ * console.log(el.nodeName);
+ * // => 'BODY'
+ * console.log(el.childNodes.length);
+ * // => 20
+ */
+ function cloneDeepWith(value, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
+ }
+
+ /**
+ * Checks if `object` conforms to `source` by invoking the predicate
+ * properties of `source` with the corresponding property values of `object`.
+ *
+ * **Note:** This method is equivalent to `_.conforms` when `source` is
+ * partially applied.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.14.0
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {boolean} Returns `true` if `object` conforms, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2 };
+ *
+ * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
+ * // => true
+ *
+ * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
+ * // => false
+ */
+ function conformsTo(object, source) {
+ return source == null || baseConformsTo(object, source, keys(source));
+ }
+
+ /**
+ * Performs a
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * comparison between two values to determine if they are equivalent.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1 };
+ * var other = { 'a': 1 };
+ *
+ * _.eq(object, object);
+ * // => true
+ *
+ * _.eq(object, other);
+ * // => false
+ *
+ * _.eq('a', 'a');
+ * // => true
+ *
+ * _.eq('a', Object('a'));
+ * // => false
+ *
+ * _.eq(NaN, NaN);
+ * // => true
+ */
+ function eq(value, other) {
+ return value === other || (value !== value && other !== other);
+ }
+
+ /**
+ * Checks if `value` is greater than `other`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.9.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than `other`,
+ * else `false`.
+ * @see _.lt
+ * @example
+ *
+ * _.gt(3, 1);
+ * // => true
+ *
+ * _.gt(3, 3);
+ * // => false
+ *
+ * _.gt(1, 3);
+ * // => false
+ */
+ var gt = createRelationalOperation(baseGt);
+
+ /**
+ * Checks if `value` is greater than or equal to `other`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.9.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than or equal to
+ * `other`, else `false`.
+ * @see _.lte
+ * @example
+ *
+ * _.gte(3, 1);
+ * // => true
+ *
+ * _.gte(3, 3);
+ * // => true
+ *
+ * _.gte(1, 3);
+ * // => false
+ */
+ var gte = createRelationalOperation(function(value, other) {
+ return value >= other;
+ });
+
+ /**
+ * Checks if `value` is likely an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
+ * else `false`.
+ * @example
+ *
+ * _.isArguments(function() { return arguments; }());
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+ var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
+ return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
+ !propertyIsEnumerable.call(value, 'callee');
+ };
+
+ /**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(document.body.children);
+ * // => false
+ *
+ * _.isArray('abc');
+ * // => false
+ *
+ * _.isArray(_.noop);
+ * // => false
+ */
+ var isArray = Array.isArray;
+
+ /**
+ * Checks if `value` is classified as an `ArrayBuffer` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
+ * @example
+ *
+ * _.isArrayBuffer(new ArrayBuffer(2));
+ * // => true
+ *
+ * _.isArrayBuffer(new Array(2));
+ * // => false
+ */
+ var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
+
+ /**
+ * Checks if `value` is array-like. A value is considered array-like if it's
+ * not a function and has a `value.length` that's an integer greater than or
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ * @example
+ *
+ * _.isArrayLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLike(document.body.children);
+ * // => true
+ *
+ * _.isArrayLike('abc');
+ * // => true
+ *
+ * _.isArrayLike(_.noop);
+ * // => false
+ */
+ function isArrayLike(value) {
+ return value != null && isLength(value.length) && !isFunction(value);
+ }
+
+ /**
+ * This method is like `_.isArrayLike` except that it also checks if `value`
+ * is an object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
+ * else `false`.
+ * @example
+ *
+ * _.isArrayLikeObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLikeObject(document.body.children);
+ * // => true
+ *
+ * _.isArrayLikeObject('abc');
+ * // => false
+ *
+ * _.isArrayLikeObject(_.noop);
+ * // => false
+ */
+ function isArrayLikeObject(value) {
+ return isObjectLike(value) && isArrayLike(value);
+ }
+
+ /**
+ * Checks if `value` is classified as a boolean primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
+ * @example
+ *
+ * _.isBoolean(false);
+ * // => true
+ *
+ * _.isBoolean(null);
+ * // => false
+ */
+ function isBoolean(value) {
+ return value === true || value === false ||
+ (isObjectLike(value) && baseGetTag(value) == boolTag);
+ }
+
+ /**
+ * Checks if `value` is a buffer.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
+ * @example
+ *
+ * _.isBuffer(new Buffer(2));
+ * // => true
+ *
+ * _.isBuffer(new Uint8Array(2));
+ * // => false
+ */
+ var isBuffer = nativeIsBuffer || stubFalse;
+
+ /**
+ * Checks if `value` is classified as a `Date` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
+ * @example
+ *
+ * _.isDate(new Date);
+ * // => true
+ *
+ * _.isDate('Mon April 23 2012');
+ * // => false
+ */
+ var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
+
+ /**
+ * Checks if `value` is likely a DOM element.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
+ * @example
+ *
+ * _.isElement(document.body);
+ * // => true
+ *
+ * _.isElement('<body>');
+ * // => false
+ */
+ function isElement(value) {
+ return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
+ }
+
+ /**
+ * Checks if `value` is an empty object, collection, map, or set.
+ *
+ * Objects are considered empty if they have no own enumerable string keyed
+ * properties.
+ *
+ * Array-like values such as `arguments` objects, arrays, buffers, strings, or
+ * jQuery-like collections are considered empty if they have a `length` of `0`.
+ * Similarly, maps and sets are considered empty if they have a `size` of `0`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is empty, else `false`.
+ * @example
+ *
+ * _.isEmpty(null);
+ * // => true
+ *
+ * _.isEmpty(true);
+ * // => true
+ *
+ * _.isEmpty(1);
+ * // => true
+ *
+ * _.isEmpty([1, 2, 3]);
+ * // => false
+ *
+ * _.isEmpty({ 'a': 1 });
+ * // => false
+ */
+ function isEmpty(value) {
+ if (value == null) {
+ return true;
+ }
+ if (isArrayLike(value) &&
+ (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
+ isBuffer(value) || isTypedArray(value) || isArguments(value))) {
+ return !value.length;
+ }
+ var tag = getTag(value);
+ if (tag == mapTag || tag == setTag) {
+ return !value.size;
+ }
+ if (isPrototype(value)) {
+ return !baseKeys(value).length;
+ }
+ for (var key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Performs a deep comparison between two values to determine if they are
+ * equivalent.
+ *
+ * **Note:** This method supports comparing arrays, array buffers, booleans,
+ * date objects, error objects, maps, numbers, `Object` objects, regexes,
+ * sets, strings, symbols, and typed arrays. `Object` objects are compared
+ * by their own, not inherited, enumerable properties. Functions and DOM
+ * nodes are compared by strict equality, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1 };
+ * var other = { 'a': 1 };
+ *
+ * _.isEqual(object, other);
+ * // => true
+ *
+ * object === other;
+ * // => false
+ */
+ function isEqual(value, other) {
+ return baseIsEqual(value, other);
+ }
+
+ /**
+ * This method is like `_.isEqual` except that it accepts `customizer` which
+ * is invoked to compare values. If `customizer` returns `undefined`, comparisons
+ * are handled by the method instead. The `customizer` is invoked with up to
+ * six arguments: (objValue, othValue [, index|key, object, other, stack]).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * function isGreeting(value) {
+ * return /^h(?:i|ello)$/.test(value);
+ * }
+ *
+ * function customizer(objValue, othValue) {
+ * if (isGreeting(objValue) && isGreeting(othValue)) {
+ * return true;
+ * }
+ * }
+ *
+ * var array = ['hello', 'goodbye'];
+ * var other = ['hi', 'goodbye'];
+ *
+ * _.isEqualWith(array, other, customizer);
+ * // => true
+ */
+ function isEqualWith(value, other, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ var result = customizer ? customizer(value, other) : undefined;
+ return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
+ }
+
+ /**
+ * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
+ * `SyntaxError`, `TypeError`, or `URIError` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
+ * @example
+ *
+ * _.isError(new Error);
+ * // => true
+ *
+ * _.isError(Error);
+ * // => false
+ */
+ function isError(value) {
+ if (!isObjectLike(value)) {
+ return false;
+ }
+ var tag = baseGetTag(value);
+ return tag == errorTag || tag == domExcTag ||
+ (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
+ }
+
+ /**
+ * Checks if `value` is a finite primitive number.
+ *
+ * **Note:** This method is based on
+ * [`Number.isFinite`](https://mdn.io/Number/isFinite).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
+ * @example
+ *
+ * _.isFinite(3);
+ * // => true
+ *
+ * _.isFinite(Number.MIN_VALUE);
+ * // => true
+ *
+ * _.isFinite(Infinity);
+ * // => false
+ *
+ * _.isFinite('3');
+ * // => false
+ */
+ function isFinite(value) {
+ return typeof value == 'number' && nativeIsFinite(value);
+ }
+
+ /**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a function, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+ function isFunction(value) {
+ if (!isObject(value)) {
+ return false;
+ }
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in Safari 9 which returns 'object' for typed arrays and other constructors.
+ var tag = baseGetTag(value);
+ return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
+ }
+
+ /**
+ * Checks if `value` is an integer.
+ *
+ * **Note:** This method is based on
+ * [`Number.isInteger`](https://mdn.io/Number/isInteger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
+ * @example
+ *
+ * _.isInteger(3);
+ * // => true
+ *
+ * _.isInteger(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isInteger(Infinity);
+ * // => false
+ *
+ * _.isInteger('3');
+ * // => false
+ */
+ function isInteger(value) {
+ return typeof value == 'number' && value == toInteger(value);
+ }
+
+ /**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ * @example
+ *
+ * _.isLength(3);
+ * // => true
+ *
+ * _.isLength(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isLength(Infinity);
+ * // => false
+ *
+ * _.isLength('3');
+ * // => false
+ */
+ function isLength(value) {
+ return typeof value == 'number' &&
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+ }
+
+ /**
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+ function isObject(value) {
+ var type = typeof value;
+ return value != null && (type == 'object' || type == 'function');
+ }
+
+ /**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+ function isObjectLike(value) {
+ return value != null && typeof value == 'object';
+ }
+
+ /**
+ * Checks if `value` is classified as a `Map` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a map, else `false`.
+ * @example
+ *
+ * _.isMap(new Map);
+ * // => true
+ *
+ * _.isMap(new WeakMap);
+ * // => false
+ */
+ var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
+
+ /**
+ * Performs a partial deep comparison between `object` and `source` to
+ * determine if `object` contains equivalent property values.
+ *
+ * **Note:** This method is equivalent to `_.matches` when `source` is
+ * partially applied.
+ *
+ * Partial comparisons will match empty array and empty object `source`
+ * values against any array or object value, respectively. See `_.isEqual`
+ * for a list of supported value comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2 };
+ *
+ * _.isMatch(object, { 'b': 2 });
+ * // => true
+ *
+ * _.isMatch(object, { 'b': 1 });
+ * // => false
+ */
+ function isMatch(object, source) {
+ return object === source || baseIsMatch(object, source, getMatchData(source));
+ }
+
+ /**
+ * This method is like `_.isMatch` except that it accepts `customizer` which
+ * is invoked to compare values. If `customizer` returns `undefined`, comparisons
+ * are handled by the method instead. The `customizer` is invoked with five
+ * arguments: (objValue, srcValue, index|key, object, source).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ * @example
+ *
+ * function isGreeting(value) {
+ * return /^h(?:i|ello)$/.test(value);
+ * }
+ *
+ * function customizer(objValue, srcValue) {
+ * if (isGreeting(objValue) && isGreeting(srcValue)) {
+ * return true;
+ * }
+ * }
+ *
+ * var object = { 'greeting': 'hello' };
+ * var source = { 'greeting': 'hi' };
+ *
+ * _.isMatchWith(object, source, customizer);
+ * // => true
+ */
+ function isMatchWith(object, source, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ return baseIsMatch(object, source, getMatchData(source), customizer);
+ }
+
+ /**
+ * Checks if `value` is `NaN`.
+ *
+ * **Note:** This method is based on
+ * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
+ * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
+ * `undefined` and other non-number values.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ * @example
+ *
+ * _.isNaN(NaN);
+ * // => true
+ *
+ * _.isNaN(new Number(NaN));
+ * // => true
+ *
+ * isNaN(undefined);
+ * // => true
+ *
+ * _.isNaN(undefined);
+ * // => false
+ */
+ function isNaN(value) {
+ // An `NaN` primitive is the only value that is not equal to itself.
+ // Perform the `toStringTag` check first to avoid errors with some
+ // ActiveX objects in IE.
+ return isNumber(value) && value != +value;
+ }
+
+ /**
+ * Checks if `value` is a pristine native function.
+ *
+ * **Note:** This method can't reliably detect native functions in the presence
+ * of the core-js package because core-js circumvents this kind of detection.
+ * Despite multiple requests, the core-js maintainer has made it clear: any
+ * attempt to fix the detection will be obstructed. As a result, we're left
+ * with little choice but to throw an error. Unfortunately, this also affects
+ * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
+ * which rely on core-js.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function,
+ * else `false`.
+ * @example
+ *
+ * _.isNative(Array.prototype.push);
+ * // => true
+ *
+ * _.isNative(_);
+ * // => false
+ */
+ function isNative(value) {
+ if (isMaskable(value)) {
+ throw new Error(CORE_ERROR_TEXT);
+ }
+ return baseIsNative(value);
+ }
+
+ /**
+ * Checks if `value` is `null`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
+ * @example
+ *
+ * _.isNull(null);
+ * // => true
+ *
+ * _.isNull(void 0);
+ * // => false
+ */
+ function isNull(value) {
+ return value === null;
+ }
+
+ /**
+ * Checks if `value` is `null` or `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
+ * @example
+ *
+ * _.isNil(null);
+ * // => true
+ *
+ * _.isNil(void 0);
+ * // => true
+ *
+ * _.isNil(NaN);
+ * // => false
+ */
+ function isNil(value) {
+ return value == null;
+ }
+
+ /**
+ * Checks if `value` is classified as a `Number` primitive or object.
+ *
+ * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
+ * classified as numbers, use the `_.isFinite` method.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a number, else `false`.
+ * @example
+ *
+ * _.isNumber(3);
+ * // => true
+ *
+ * _.isNumber(Number.MIN_VALUE);
+ * // => true
+ *
+ * _.isNumber(Infinity);
+ * // => true
+ *
+ * _.isNumber('3');
+ * // => false
+ */
+ function isNumber(value) {
+ return typeof value == 'number' ||
+ (isObjectLike(value) && baseGetTag(value) == numberTag);
+ }
+
+ /**
+ * Checks if `value` is a plain object, that is, an object created by the
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.8.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * _.isPlainObject(new Foo);
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
+ * // => true
+ *
+ * _.isPlainObject(Object.create(null));
+ * // => true
+ */
+ function isPlainObject(value) {
+ if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
+ return false;
+ }
+ var proto = getPrototype(value);
+ if (proto === null) {
+ return true;
+ }
+ var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
+ return typeof Ctor == 'function' && Ctor instanceof Ctor &&
+ funcToString.call(Ctor) == objectCtorString;
+ }
+
+ /**
+ * Checks if `value` is classified as a `RegExp` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
+ * @example
+ *
+ * _.isRegExp(/abc/);
+ * // => true
+ *
+ * _.isRegExp('/abc/');
+ * // => false
+ */
+ var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
+
+ /**
+ * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
+ * double precision number which isn't the result of a rounded unsafe integer.
+ *
+ * **Note:** This method is based on
+ * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
+ * @example
+ *
+ * _.isSafeInteger(3);
+ * // => true
+ *
+ * _.isSafeInteger(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isSafeInteger(Infinity);
+ * // => false
+ *
+ * _.isSafeInteger('3');
+ * // => false
+ */
+ function isSafeInteger(value) {
+ return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
+ }
+
+ /**
+ * Checks if `value` is classified as a `Set` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a set, else `false`.
+ * @example
+ *
+ * _.isSet(new Set);
+ * // => true
+ *
+ * _.isSet(new WeakSet);
+ * // => false
+ */
+ var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
+
+ /**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a string, else `false`.
+ * @example
+ *
+ * _.isString('abc');
+ * // => true
+ *
+ * _.isString(1);
+ * // => false
+ */
+ function isString(value) {
+ return typeof value == 'string' ||
+ (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
+ }
+
+ /**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
+ * @example
+ *
+ * _.isSymbol(Symbol.iterator);
+ * // => true
+ *
+ * _.isSymbol('abc');
+ * // => false
+ */
+ function isSymbol(value) {
+ return typeof value == 'symbol' ||
+ (isObjectLike(value) && baseGetTag(value) == symbolTag);
+ }
+
+ /**
+ * Checks if `value` is classified as a typed array.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
+ * @example
+ *
+ * _.isTypedArray(new Uint8Array);
+ * // => true
+ *
+ * _.isTypedArray([]);
+ * // => false
+ */
+ var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
+
+ /**
+ * Checks if `value` is `undefined`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
+ * @example
+ *
+ * _.isUndefined(void 0);
+ * // => true
+ *
+ * _.isUndefined(null);
+ * // => false
+ */
+ function isUndefined(value) {
+ return value === undefined;
+ }
+
+ /**
+ * Checks if `value` is classified as a `WeakMap` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
+ * @example
+ *
+ * _.isWeakMap(new WeakMap);
+ * // => true
+ *
+ * _.isWeakMap(new Map);
+ * // => false
+ */
+ function isWeakMap(value) {
+ return isObjectLike(value) && getTag(value) == weakMapTag;
+ }
+
+ /**
+ * Checks if `value` is classified as a `WeakSet` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
+ * @example
+ *
+ * _.isWeakSet(new WeakSet);
+ * // => true
+ *
+ * _.isWeakSet(new Set);
+ * // => false
+ */
+ function isWeakSet(value) {
+ return isObjectLike(value) && baseGetTag(value) == weakSetTag;
+ }
+
+ /**
+ * Checks if `value` is less than `other`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.9.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than `other`,
+ * else `false`.
+ * @see _.gt
+ * @example
+ *
+ * _.lt(1, 3);
+ * // => true
+ *
+ * _.lt(3, 3);
+ * // => false
+ *
+ * _.lt(3, 1);
+ * // => false
+ */
+ var lt = createRelationalOperation(baseLt);
+
+ /**
+ * Checks if `value` is less than or equal to `other`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.9.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than or equal to
+ * `other`, else `false`.
+ * @see _.gte
+ * @example
+ *
+ * _.lte(1, 3);
+ * // => true
+ *
+ * _.lte(3, 3);
+ * // => true
+ *
+ * _.lte(3, 1);
+ * // => false
+ */
+ var lte = createRelationalOperation(function(value, other) {
+ return value <= other;
+ });
+
+ /**
+ * Converts `value` to an array.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Array} Returns the converted array.
+ * @example
+ *
+ * _.toArray({ 'a': 1, 'b': 2 });
+ * // => [1, 2]
+ *
+ * _.toArray('abc');
+ * // => ['a', 'b', 'c']
+ *
+ * _.toArray(1);
+ * // => []
+ *
+ * _.toArray(null);
+ * // => []
+ */
+ function toArray(value) {
+ if (!value) {
+ return [];
+ }
+ if (isArrayLike(value)) {
+ return isString(value) ? stringToArray(value) : copyArray(value);
+ }
+ if (symIterator && value[symIterator]) {
+ return iteratorToArray(value[symIterator]());
+ }
+ var tag = getTag(value),
+ func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
+
+ return func(value);
+ }
+
+ /**
+ * Converts `value` to a finite number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.12.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted number.
+ * @example
+ *
+ * _.toFinite(3.2);
+ * // => 3.2
+ *
+ * _.toFinite(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toFinite(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toFinite('3.2');
+ * // => 3.2
+ */
+ function toFinite(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = (value < 0 ? -1 : 1);
+ return sign * MAX_INTEGER;
+ }
+ return value === value ? value : 0;
+ }
+
+ /**
+ * Converts `value` to an integer.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toInteger(3.2);
+ * // => 3
+ *
+ * _.toInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toInteger(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toInteger('3.2');
+ * // => 3
+ */
+ function toInteger(value) {
+ var result = toFinite(value),
+ remainder = result % 1;
+
+ return result === result ? (remainder ? result - remainder : result) : 0;
+ }
+
+ /**
+ * Converts `value` to an integer suitable for use as the length of an
+ * array-like object.
+ *
+ * **Note:** This method is based on
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toLength(3.2);
+ * // => 3
+ *
+ * _.toLength(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toLength(Infinity);
+ * // => 4294967295
+ *
+ * _.toLength('3.2');
+ * // => 3
+ */
+ function toLength(value) {
+ return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
+ }
+
+ /**
+ * Converts `value` to a number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ * @example
+ *
+ * _.toNumber(3.2);
+ * // => 3.2
+ *
+ * _.toNumber(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toNumber(Infinity);
+ * // => Infinity
+ *
+ * _.toNumber('3.2');
+ * // => 3.2
+ */
+ function toNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
+ value = isObject(other) ? (other + '') : other;
+ }
+ if (typeof value != 'string') {
+ return value === 0 ? value : +value;
+ }
+ value = value.replace(reTrim, '');
+ var isBinary = reIsBinary.test(value);
+ return (isBinary || reIsOctal.test(value))
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
+ : (reIsBadHex.test(value) ? NAN : +value);
+ }
+
+ /**
+ * Converts `value` to a plain object flattening inherited enumerable string
+ * keyed properties of `value` to own properties of the plain object.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Object} Returns the converted plain object.
+ * @example
+ *
+ * function Foo() {
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.assign({ 'a': 1 }, new Foo);
+ * // => { 'a': 1, 'b': 2 }
+ *
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
+ */
+ function toPlainObject(value) {
+ return copyObject(value, keysIn(value));
+ }
+
+ /**
+ * Converts `value` to a safe integer. A safe integer can be compared and
+ * represented correctly.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toSafeInteger(3.2);
+ * // => 3
+ *
+ * _.toSafeInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toSafeInteger(Infinity);
+ * // => 9007199254740991
+ *
+ * _.toSafeInteger('3.2');
+ * // => 3
+ */
+ function toSafeInteger(value) {
+ return value
+ ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
+ : (value === 0 ? value : 0);
+ }
+
+ /**
+ * Converts `value` to a string. An empty string is returned for `null`
+ * and `undefined` values. The sign of `-0` is preserved.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {string} Returns the converted string.
+ * @example
+ *
+ * _.toString(null);
+ * // => ''
+ *
+ * _.toString(-0);
+ * // => '-0'
+ *
+ * _.toString([1, 2, 3]);
+ * // => '1,2,3'
+ */
+ function toString(value) {
+ return value == null ? '' : baseToString(value);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Assigns own enumerable string keyed properties of source objects to the
+ * destination object. Source objects are applied from left to right.
+ * Subsequent sources overwrite property assignments of previous sources.
+ *
+ * **Note:** This method mutates `object` and is loosely based on
+ * [`Object.assign`](https://mdn.io/Object/assign).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.10.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.assignIn
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * function Bar() {
+ * this.c = 3;
+ * }
+ *
+ * Foo.prototype.b = 2;
+ * Bar.prototype.d = 4;
+ *
+ * _.assign({ 'a': 0 }, new Foo, new Bar);
+ * // => { 'a': 1, 'c': 3 }
+ */
+ var assign = createAssigner(function(object, source) {
+ if (isPrototype(source) || isArrayLike(source)) {
+ copyObject(source, keys(source), object);
+ return;
+ }
+ for (var key in source) {
+ if (hasOwnProperty.call(source, key)) {
+ assignValue(object, key, source[key]);
+ }
+ }
+ });
+
+ /**
+ * This method is like `_.assign` except that it iterates over own and
+ * inherited source properties.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @alias extend
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.assign
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * function Bar() {
+ * this.c = 3;
+ * }
+ *
+ * Foo.prototype.b = 2;
+ * Bar.prototype.d = 4;
+ *
+ * _.assignIn({ 'a': 0 }, new Foo, new Bar);
+ * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
+ */
+ var assignIn = createAssigner(function(object, source) {
+ copyObject(source, keysIn(source), object);
+ });
+
+ /**
+ * This method is like `_.assignIn` except that it accepts `customizer`
+ * which is invoked to produce the assigned values. If `customizer` returns
+ * `undefined`, assignment is handled by the method instead. The `customizer`
+ * is invoked with five arguments: (objValue, srcValue, key, object, source).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @alias extendWith
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @see _.assignWith
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * return _.isUndefined(objValue) ? srcValue : objValue;
+ * }
+ *
+ * var defaults = _.partialRight(_.assignInWith, customizer);
+ *
+ * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+ var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObject(source, keysIn(source), object, customizer);
+ });
+
+ /**
+ * This method is like `_.assign` except that it accepts `customizer`
+ * which is invoked to produce the assigned values. If `customizer` returns
+ * `undefined`, assignment is handled by the method instead. The `customizer`
+ * is invoked with five arguments: (objValue, srcValue, key, object, source).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @see _.assignInWith
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * return _.isUndefined(objValue) ? srcValue : objValue;
+ * }
+ *
+ * var defaults = _.partialRight(_.assignWith, customizer);
+ *
+ * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+ var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObject(source, keys(source), object, customizer);
+ });
+
+ /**
+ * Creates an array of values corresponding to `paths` of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.0.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {...(string|string[])} [paths] The property paths to pick.
+ * @returns {Array} Returns the picked values.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
+ *
+ * _.at(object, ['a[0].b.c', 'a[1]']);
+ * // => [3, 4]
+ */
+ var at = flatRest(baseAt);
+
+ /**
+ * Creates an object that inherits from the `prototype` object. If a
+ * `properties` object is given, its own enumerable string keyed properties
+ * are assigned to the created object.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.3.0
+ * @category Object
+ * @param {Object} prototype The object to inherit from.
+ * @param {Object} [properties] The properties to assign to the object.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * function Shape() {
+ * this.x = 0;
+ * this.y = 0;
+ * }
+ *
+ * function Circle() {
+ * Shape.call(this);
+ * }
+ *
+ * Circle.prototype = _.create(Shape.prototype, {
+ * 'constructor': Circle
+ * });
+ *
+ * var circle = new Circle;
+ * circle instanceof Circle;
+ * // => true
+ *
+ * circle instanceof Shape;
+ * // => true
+ */
+ function create(prototype, properties) {
+ var result = baseCreate(prototype);
+ return properties == null ? result : baseAssign(result, properties);
+ }
+
+ /**
+ * Assigns own and inherited enumerable string keyed properties of source
+ * objects to the destination object for all destination properties that
+ * resolve to `undefined`. Source objects are applied from left to right.
+ * Once a property is set, additional values of the same property are ignored.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.defaultsDeep
+ * @example
+ *
+ * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+ var defaults = baseRest(function(args) {
+ args.push(undefined, customDefaultsAssignIn);
+ return apply(assignInWith, undefined, args);
+ });
+
+ /**
+ * This method is like `_.defaults` except that it recursively assigns
+ * default properties.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.10.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.defaults
+ * @example
+ *
+ * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
+ * // => { 'a': { 'b': 2, 'c': 3 } }
+ */
+ var defaultsDeep = baseRest(function(args) {
+ args.push(undefined, customDefaultsMerge);
+ return apply(mergeWith, undefined, args);
+ });
+
+ /**
+ * This method is like `_.find` except that it returns the key of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {string|undefined} Returns the key of the matched element,
+ * else `undefined`.
+ * @example
+ *
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findKey(users, function(o) { return o.age < 40; });
+ * // => 'barney' (iteration order is not guaranteed)
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findKey(users, { 'age': 1, 'active': true });
+ * // => 'pebbles'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findKey(users, ['active', false]);
+ * // => 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findKey(users, 'active');
+ * // => 'barney'
+ */
+ function findKey(object, predicate) {
+ return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
+ }
+
+ /**
+ * This method is like `_.findKey` except that it iterates over elements of
+ * a collection in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {string|undefined} Returns the key of the matched element,
+ * else `undefined`.
+ * @example
+ *
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findLastKey(users, function(o) { return o.age < 40; });
+ * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findLastKey(users, { 'age': 36, 'active': true });
+ * // => 'barney'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findLastKey(users, ['active', false]);
+ * // => 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findLastKey(users, 'active');
+ * // => 'pebbles'
+ */
+ function findLastKey(object, predicate) {
+ return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
+ }
+
+ /**
+ * Iterates over own and inherited enumerable string keyed properties of an
+ * object and invokes `iteratee` for each property. The iteratee is invoked
+ * with three arguments: (value, key, object). Iteratee functions may exit
+ * iteration early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.3.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forInRight
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forIn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
+ */
+ function forIn(object, iteratee) {
+ return object == null
+ ? object
+ : baseFor(object, getIteratee(iteratee, 3), keysIn);
+ }
+
+ /**
+ * This method is like `_.forIn` except that it iterates over properties of
+ * `object` in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forIn
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forInRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
+ */
+ function forInRight(object, iteratee) {
+ return object == null
+ ? object
+ : baseForRight(object, getIteratee(iteratee, 3), keysIn);
+ }
+
+ /**
+ * Iterates over own enumerable string keyed properties of an object and
+ * invokes `iteratee` for each property. The iteratee is invoked with three
+ * arguments: (value, key, object). Iteratee functions may exit iteration
+ * early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.3.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forOwnRight
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'a' then 'b' (iteration order is not guaranteed).
+ */
+ function forOwn(object, iteratee) {
+ return object && baseForOwn(object, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * This method is like `_.forOwn` except that it iterates over properties of
+ * `object` in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forOwn
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwnRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
+ */
+ function forOwnRight(object, iteratee) {
+ return object && baseForOwnRight(object, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * Creates an array of function property names from own enumerable properties
+ * of `object`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns the function names.
+ * @see _.functionsIn
+ * @example
+ *
+ * function Foo() {
+ * this.a = _.constant('a');
+ * this.b = _.constant('b');
+ * }
+ *
+ * Foo.prototype.c = _.constant('c');
+ *
+ * _.functions(new Foo);
+ * // => ['a', 'b']
+ */
+ function functions(object) {
+ return object == null ? [] : baseFunctions(object, keys(object));
+ }
+
+ /**
+ * Creates an array of function property names from own and inherited
+ * enumerable properties of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns the function names.
+ * @see _.functions
+ * @example
+ *
+ * function Foo() {
+ * this.a = _.constant('a');
+ * this.b = _.constant('b');
+ * }
+ *
+ * Foo.prototype.c = _.constant('c');
+ *
+ * _.functionsIn(new Foo);
+ * // => ['a', 'b', 'c']
+ */
+ function functionsIn(object) {
+ return object == null ? [] : baseFunctions(object, keysIn(object));
+ }
+
+ /**
+ * Gets the value at `path` of `object`. If the resolved value is
+ * `undefined`, the `defaultValue` is returned in its place.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.7.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} [defaultValue] The value returned for `undefined` resolved values.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.get(object, 'a[0].b.c');
+ * // => 3
+ *
+ * _.get(object, ['a', '0', 'b', 'c']);
+ * // => 3
+ *
+ * _.get(object, 'a.b.c', 'default');
+ * // => 'default'
+ */
+ function get(object, path, defaultValue) {
+ var result = object == null ? undefined : baseGet(object, path);
+ return result === undefined ? defaultValue : result;
+ }
+
+ /**
+ * Checks if `path` is a direct property of `object`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ * @example
+ *
+ * var object = { 'a': { 'b': 2 } };
+ * var other = _.create({ 'a': _.create({ 'b': 2 }) });
+ *
+ * _.has(object, 'a');
+ * // => true
+ *
+ * _.has(object, 'a.b');
+ * // => true
+ *
+ * _.has(object, ['a', 'b']);
+ * // => true
+ *
+ * _.has(other, 'a');
+ * // => false
+ */
+ function has(object, path) {
+ return object != null && hasPath(object, path, baseHas);
+ }
+
+ /**
+ * Checks if `path` is a direct or inherited property of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ * @example
+ *
+ * var object = _.create({ 'a': _.create({ 'b': 2 }) });
+ *
+ * _.hasIn(object, 'a');
+ * // => true
+ *
+ * _.hasIn(object, 'a.b');
+ * // => true
+ *
+ * _.hasIn(object, ['a', 'b']);
+ * // => true
+ *
+ * _.hasIn(object, 'b');
+ * // => false
+ */
+ function hasIn(object, path) {
+ return object != null && hasPath(object, path, baseHasIn);
+ }
+
+ /**
+ * Creates an object composed of the inverted keys and values of `object`.
+ * If `object` contains duplicate values, subsequent values overwrite
+ * property assignments of previous values.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.7.0
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @returns {Object} Returns the new inverted object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
+ *
+ * _.invert(object);
+ * // => { '1': 'c', '2': 'b' }
+ */
+ var invert = createInverter(function(result, value, key) {
+ result[value] = key;
+ }, constant(identity));
+
+ /**
+ * This method is like `_.invert` except that the inverted object is generated
+ * from the results of running each element of `object` thru `iteratee`. The
+ * corresponding inverted value of each inverted key is an array of keys
+ * responsible for generating the inverted value. The iteratee is invoked
+ * with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.1.0
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Object} Returns the new inverted object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
+ *
+ * _.invertBy(object);
+ * // => { '1': ['a', 'c'], '2': ['b'] }
+ *
+ * _.invertBy(object, function(value) {
+ * return 'group' + value;
+ * });
+ * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
+ */
+ var invertBy = createInverter(function(result, value, key) {
+ if (hasOwnProperty.call(result, value)) {
+ result[value].push(key);
+ } else {
+ result[value] = [key];
+ }
+ }, getIteratee);
+
+ /**
+ * Invokes the method at `path` of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {*} Returns the result of the invoked method.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
+ *
+ * _.invoke(object, 'a[0].b.c.slice', 1, 3);
+ * // => [2, 3]
+ */
+ var invoke = baseRest(baseInvoke);
+
+ /**
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * for more details.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keys(new Foo);
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * _.keys('hi');
+ * // => ['0', '1']
+ */
+ function keys(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
+ }
+
+ /**
+ * Creates an array of the own and inherited enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keysIn(new Foo);
+ * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
+ */
+ function keysIn(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
+ }
+
+ /**
+ * The opposite of `_.mapValues`; this method creates an object with the
+ * same values as `object` and keys generated by running each own enumerable
+ * string keyed property of `object` thru `iteratee`. The iteratee is invoked
+ * with three arguments: (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.8.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns the new mapped object.
+ * @see _.mapValues
+ * @example
+ *
+ * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
+ * return key + value;
+ * });
+ * // => { 'a1': 1, 'b2': 2 }
+ */
+ function mapKeys(object, iteratee) {
+ var result = {};
+ iteratee = getIteratee(iteratee, 3);
+
+ baseForOwn(object, function(value, key, object) {
+ baseAssignValue(result, iteratee(value, key, object), value);
+ });
+ return result;
+ }
+
+ /**
+ * Creates an object with the same keys as `object` and values generated
+ * by running each own enumerable string keyed property of `object` thru
+ * `iteratee`. The iteratee is invoked with three arguments:
+ * (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns the new mapped object.
+ * @see _.mapKeys
+ * @example
+ *
+ * var users = {
+ * 'fred': { 'user': 'fred', 'age': 40 },
+ * 'pebbles': { 'user': 'pebbles', 'age': 1 }
+ * };
+ *
+ * _.mapValues(users, function(o) { return o.age; });
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.mapValues(users, 'age');
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ */
+ function mapValues(object, iteratee) {
+ var result = {};
+ iteratee = getIteratee(iteratee, 3);
+
+ baseForOwn(object, function(value, key, object) {
+ baseAssignValue(result, key, iteratee(value, key, object));
+ });
+ return result;
+ }
+
+ /**
+ * This method is like `_.assign` except that it recursively merges own and
+ * inherited enumerable string keyed properties of source objects into the
+ * destination object. Source properties that resolve to `undefined` are
+ * skipped if a destination value exists. Array and plain object properties
+ * are merged recursively. Other objects and value types are overridden by
+ * assignment. Source objects are applied from left to right. Subsequent
+ * sources overwrite property assignments of previous sources.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.5.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {
+ * 'a': [{ 'b': 2 }, { 'd': 4 }]
+ * };
+ *
+ * var other = {
+ * 'a': [{ 'c': 3 }, { 'e': 5 }]
+ * };
+ *
+ * _.merge(object, other);
+ * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
+ */
+ var merge = createAssigner(function(object, source, srcIndex) {
+ baseMerge(object, source, srcIndex);
+ });
+
+ /**
+ * This method is like `_.merge` except that it accepts `customizer` which
+ * is invoked to produce the merged values of the destination and source
+ * properties. If `customizer` returns `undefined`, merging is handled by the
+ * method instead. The `customizer` is invoked with six arguments:
+ * (objValue, srcValue, key, object, source, stack).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} customizer The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * if (_.isArray(objValue)) {
+ * return objValue.concat(srcValue);
+ * }
+ * }
+ *
+ * var object = { 'a': [1], 'b': [2] };
+ * var other = { 'a': [3], 'b': [4] };
+ *
+ * _.mergeWith(object, other, customizer);
+ * // => { 'a': [1, 3], 'b': [2, 4] }
+ */
+ var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
+ baseMerge(object, source, srcIndex, customizer);
+ });
+
+ /**
+ * The opposite of `_.pick`; this method creates an object composed of the
+ * own and inherited enumerable property paths of `object` that are not omitted.
+ *
+ * **Note:** This method is considerably slower than `_.pick`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {...(string|string[])} [paths] The property paths to omit.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.omit(object, ['a', 'c']);
+ * // => { 'b': '2' }
+ */
+ var omit = flatRest(function(object, paths) {
+ var result = {};
+ if (object == null) {
+ return result;
+ }
+ var isDeep = false;
+ paths = arrayMap(paths, function(path) {
+ path = castPath(path, object);
+ isDeep || (isDeep = path.length > 1);
+ return path;
+ });
+ copyObject(object, getAllKeysIn(object), result);
+ if (isDeep) {
+ result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
+ }
+ var length = paths.length;
+ while (length--) {
+ baseUnset(result, paths[length]);
+ }
+ return result;
+ });
+
+ /**
+ * The opposite of `_.pickBy`; this method creates an object composed of
+ * the own and inherited enumerable string keyed properties of `object` that
+ * `predicate` doesn't return truthy for. The predicate is invoked with two
+ * arguments: (value, key).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function} [predicate=_.identity] The function invoked per property.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.omitBy(object, _.isNumber);
+ * // => { 'b': '2' }
+ */
+ function omitBy(object, predicate) {
+ return pickBy(object, negate(getIteratee(predicate)));
+ }
+
+ /**
+ * Creates an object composed of the picked `object` properties.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {...(string|string[])} [paths] The property paths to pick.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.pick(object, ['a', 'c']);
+ * // => { 'a': 1, 'c': 3 }
+ */
+ var pick = flatRest(function(object, paths) {
+ return object == null ? {} : basePick(object, paths);
+ });
+
+ /**
+ * Creates an object composed of the `object` properties `predicate` returns
+ * truthy for. The predicate is invoked with two arguments: (value, key).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function} [predicate=_.identity] The function invoked per property.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.pickBy(object, _.isNumber);
+ * // => { 'a': 1, 'c': 3 }
+ */
+ function pickBy(object, predicate) {
+ if (object == null) {
+ return {};
+ }
+ var props = arrayMap(getAllKeysIn(object), function(prop) {
+ return [prop];
+ });
+ predicate = getIteratee(predicate);
+ return basePickBy(object, props, function(value, path) {
+ return predicate(value, path[0]);
+ });
+ }
+
+ /**
+ * This method is like `_.get` except that if the resolved value is a
+ * function it's invoked with the `this` binding of its parent object and
+ * its result is returned.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to resolve.
+ * @param {*} [defaultValue] The value returned for `undefined` resolved values.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
+ *
+ * _.result(object, 'a[0].b.c1');
+ * // => 3
+ *
+ * _.result(object, 'a[0].b.c2');
+ * // => 4
+ *
+ * _.result(object, 'a[0].b.c3', 'default');
+ * // => 'default'
+ *
+ * _.result(object, 'a[0].b.c3', _.constant('default'));
+ * // => 'default'
+ */
+ function result(object, path, defaultValue) {
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length;
+
+ // Ensure the loop is entered when path is empty.
+ if (!length) {
+ length = 1;
+ object = undefined;
+ }
+ while (++index < length) {
+ var value = object == null ? undefined : object[toKey(path[index])];
+ if (value === undefined) {
+ index = length;
+ value = defaultValue;
+ }
+ object = isFunction(value) ? value.call(object) : value;
+ }
+ return object;
+ }
+
+ /**
+ * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
+ * it's created. Arrays are created for missing index properties while objects
+ * are created for all other missing properties. Use `_.setWith` to customize
+ * `path` creation.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.7.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.set(object, 'a[0].b.c', 4);
+ * console.log(object.a[0].b.c);
+ * // => 4
+ *
+ * _.set(object, ['x', '0', 'y', 'z'], 5);
+ * console.log(object.x[0].y.z);
+ * // => 5
+ */
+ function set(object, path, value) {
+ return object == null ? object : baseSet(object, path, value);
+ }
+
+ /**
+ * This method is like `_.set` except that it accepts `customizer` which is
+ * invoked to produce the objects of `path`. If `customizer` returns `undefined`
+ * path creation is handled by the method instead. The `customizer` is invoked
+ * with three arguments: (nsValue, key, nsObject).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {};
+ *
+ * _.setWith(object, '[0][1]', 'a', Object);
+ * // => { '0': { '1': 'a' } }
+ */
+ function setWith(object, path, value, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ return object == null ? object : baseSet(object, path, value, customizer);
+ }
+
+ /**
+ * Creates an array of own enumerable string keyed-value pairs for `object`
+ * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
+ * entries are returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @alias entries
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the key-value pairs.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.toPairs(new Foo);
+ * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
+ */
+ var toPairs = createToPairs(keys);
+
+ /**
+ * Creates an array of own and inherited enumerable string keyed-value pairs
+ * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
+ * or set, its entries are returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @alias entriesIn
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the key-value pairs.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.toPairsIn(new Foo);
+ * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
+ */
+ var toPairsIn = createToPairs(keysIn);
+
+ /**
+ * An alternative to `_.reduce`; this method transforms `object` to a new
+ * `accumulator` object which is the result of running each of its own
+ * enumerable string keyed properties thru `iteratee`, with each invocation
+ * potentially mutating the `accumulator` object. If `accumulator` is not
+ * provided, a new object with the same `[[Prototype]]` will be used. The
+ * iteratee is invoked with four arguments: (accumulator, value, key, object).
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.3.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The custom accumulator value.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * _.transform([2, 3, 4], function(result, n) {
+ * result.push(n *= n);
+ * return n % 2 == 0;
+ * }, []);
+ * // => [4, 9]
+ *
+ * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
+ * (result[value] || (result[value] = [])).push(key);
+ * }, {});
+ * // => { '1': ['a', 'c'], '2': ['b'] }
+ */
+ function transform(object, iteratee, accumulator) {
+ var isArr = isArray(object),
+ isArrLike = isArr || isBuffer(object) || isTypedArray(object);
+
+ iteratee = getIteratee(iteratee, 4);
+ if (accumulator == null) {
+ var Ctor = object && object.constructor;
+ if (isArrLike) {
+ accumulator = isArr ? new Ctor : [];
+ }
+ else if (isObject(object)) {
+ accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
+ }
+ else {
+ accumulator = {};
+ }
+ }
+ (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
+ return iteratee(accumulator, value, index, object);
+ });
+ return accumulator;
+ }
+
+ /**
+ * Removes the property at `path` of `object`.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to unset.
+ * @returns {boolean} Returns `true` if the property is deleted, else `false`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 7 } }] };
+ * _.unset(object, 'a[0].b.c');
+ * // => true
+ *
+ * console.log(object);
+ * // => { 'a': [{ 'b': {} }] };
+ *
+ * _.unset(object, ['a', '0', 'b', 'c']);
+ * // => true
+ *
+ * console.log(object);
+ * // => { 'a': [{ 'b': {} }] };
+ */
+ function unset(object, path) {
+ return object == null ? true : baseUnset(object, path);
+ }
+
+ /**
+ * This method is like `_.set` except that accepts `updater` to produce the
+ * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
+ * is invoked with one argument: (value).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.6.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {Function} updater The function to produce the updated value.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.update(object, 'a[0].b.c', function(n) { return n * n; });
+ * console.log(object.a[0].b.c);
+ * // => 9
+ *
+ * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
+ * console.log(object.x[0].y.z);
+ * // => 0
+ */
+ function update(object, path, updater) {
+ return object == null ? object : baseUpdate(object, path, castFunction(updater));
+ }
+
+ /**
+ * This method is like `_.update` except that it accepts `customizer` which is
+ * invoked to produce the objects of `path`. If `customizer` returns `undefined`
+ * path creation is handled by the method instead. The `customizer` is invoked
+ * with three arguments: (nsValue, key, nsObject).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.6.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {Function} updater The function to produce the updated value.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {};
+ *
+ * _.updateWith(object, '[0][1]', _.constant('a'), Object);
+ * // => { '0': { '1': 'a' } }
+ */
+ function updateWith(object, path, updater, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
+ }
+
+ /**
+ * Creates an array of the own enumerable string keyed property values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.values(new Foo);
+ * // => [1, 2] (iteration order is not guaranteed)
+ *
+ * _.values('hi');
+ * // => ['h', 'i']
+ */
+ function values(object) {
+ return object == null ? [] : baseValues(object, keys(object));
+ }
+
+ /**
+ * Creates an array of the own and inherited enumerable string keyed property
+ * values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.valuesIn(new Foo);
+ * // => [1, 2, 3] (iteration order is not guaranteed)
+ */
+ function valuesIn(object) {
+ return object == null ? [] : baseValues(object, keysIn(object));
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Clamps `number` within the inclusive `lower` and `upper` bounds.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Number
+ * @param {number} number The number to clamp.
+ * @param {number} [lower] The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the clamped number.
+ * @example
+ *
+ * _.clamp(-10, -5, 5);
+ * // => -5
+ *
+ * _.clamp(10, -5, 5);
+ * // => 5
+ */
+ function clamp(number, lower, upper) {
+ if (upper === undefined) {
+ upper = lower;
+ lower = undefined;
+ }
+ if (upper !== undefined) {
+ upper = toNumber(upper);
+ upper = upper === upper ? upper : 0;
+ }
+ if (lower !== undefined) {
+ lower = toNumber(lower);
+ lower = lower === lower ? lower : 0;
+ }
+ return baseClamp(toNumber(number), lower, upper);
+ }
+
+ /**
+ * Checks if `n` is between `start` and up to, but not including, `end`. If
+ * `end` is not specified, it's set to `start` with `start` then set to `0`.
+ * If `start` is greater than `end` the params are swapped to support
+ * negative ranges.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.3.0
+ * @category Number
+ * @param {number} number The number to check.
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
+ * @see _.range, _.rangeRight
+ * @example
+ *
+ * _.inRange(3, 2, 4);
+ * // => true
+ *
+ * _.inRange(4, 8);
+ * // => true
+ *
+ * _.inRange(4, 2);
+ * // => false
+ *
+ * _.inRange(2, 2);
+ * // => false
+ *
+ * _.inRange(1.2, 2);
+ * // => true
+ *
+ * _.inRange(5.2, 4);
+ * // => false
+ *
+ * _.inRange(-3, -2, -6);
+ * // => true
+ */
+ function inRange(number, start, end) {
+ start = toFinite(start);
+ if (end === undefined) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ number = toNumber(number);
+ return baseInRange(number, start, end);
+ }
+
+ /**
+ * Produces a random number between the inclusive `lower` and `upper` bounds.
+ * If only one argument is provided a number between `0` and the given number
+ * is returned. If `floating` is `true`, or either `lower` or `upper` are
+ * floats, a floating-point number is returned instead of an integer.
+ *
+ * **Note:** JavaScript follows the IEEE-754 standard for resolving
+ * floating-point values which can produce unexpected results.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.7.0
+ * @category Number
+ * @param {number} [lower=0] The lower bound.
+ * @param {number} [upper=1] The upper bound.
+ * @param {boolean} [floating] Specify returning a floating-point number.
+ * @returns {number} Returns the random number.
+ * @example
+ *
+ * _.random(0, 5);
+ * // => an integer between 0 and 5
+ *
+ * _.random(5);
+ * // => also an integer between 0 and 5
+ *
+ * _.random(5, true);
+ * // => a floating-point number between 0 and 5
+ *
+ * _.random(1.2, 5.2);
+ * // => a floating-point number between 1.2 and 5.2
+ */
+ function random(lower, upper, floating) {
+ if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
+ upper = floating = undefined;
+ }
+ if (floating === undefined) {
+ if (typeof upper == 'boolean') {
+ floating = upper;
+ upper = undefined;
+ }
+ else if (typeof lower == 'boolean') {
+ floating = lower;
+ lower = undefined;
+ }
+ }
+ if (lower === undefined && upper === undefined) {
+ lower = 0;
+ upper = 1;
+ }
+ else {
+ lower = toFinite(lower);
+ if (upper === undefined) {
+ upper = lower;
+ lower = 0;
+ } else {
+ upper = toFinite(upper);
+ }
+ }
+ if (lower > upper) {
+ var temp = lower;
+ lower = upper;
+ upper = temp;
+ }
+ if (floating || lower % 1 || upper % 1) {
+ var rand = nativeRandom();
+ return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
+ }
+ return baseRandom(lower, upper);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the camel cased string.
+ * @example
+ *
+ * _.camelCase('Foo Bar');
+ * // => 'fooBar'
+ *
+ * _.camelCase('--foo-bar--');
+ * // => 'fooBar'
+ *
+ * _.camelCase('__FOO_BAR__');
+ * // => 'fooBar'
+ */
+ var camelCase = createCompounder(function(result, word, index) {
+ word = word.toLowerCase();
+ return result + (index ? capitalize(word) : word);
+ });
+
+ /**
+ * Converts the first character of `string` to upper case and the remaining
+ * to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to capitalize.
+ * @returns {string} Returns the capitalized string.
+ * @example
+ *
+ * _.capitalize('FRED');
+ * // => 'Fred'
+ */
+ function capitalize(string) {
+ return upperFirst(toString(string).toLowerCase());
+ }
+
+ /**
+ * Deburrs `string` by converting
+ * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
+ * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
+ * letters to basic Latin letters and removing
+ * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to deburr.
+ * @returns {string} Returns the deburred string.
+ * @example
+ *
+ * _.deburr('déjà vu');
+ * // => 'deja vu'
+ */
+ function deburr(string) {
+ string = toString(string);
+ return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
+ }
+
+ /**
+ * Checks if `string` ends with the given target string.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to inspect.
+ * @param {string} [target] The string to search for.
+ * @param {number} [position=string.length] The position to search up to.
+ * @returns {boolean} Returns `true` if `string` ends with `target`,
+ * else `false`.
+ * @example
+ *
+ * _.endsWith('abc', 'c');
+ * // => true
+ *
+ * _.endsWith('abc', 'b');
+ * // => false
+ *
+ * _.endsWith('abc', 'b', 2);
+ * // => true
+ */
+ function endsWith(string, target, position) {
+ string = toString(string);
+ target = baseToString(target);
+
+ var length = string.length;
+ position = position === undefined
+ ? length
+ : baseClamp(toInteger(position), 0, length);
+
+ var end = position;
+ position -= target.length;
+ return position >= 0 && string.slice(position, end) == target;
+ }
+
+ /**
+ * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
+ * corresponding HTML entities.
+ *
+ * **Note:** No other characters are escaped. To escape additional
+ * characters use a third-party library like [_he_](https://mths.be/he).
+ *
+ * Though the ">" character is escaped for symmetry, characters like
+ * ">" and "/" don't need escaping in HTML and have no special meaning
+ * unless they're part of a tag or unquoted attribute value. See
+ * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
+ * (under "semi-related fun fact") for more details.
+ *
+ * When working with HTML you should always
+ * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
+ * XSS vectors.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to escape.
+ * @returns {string} Returns the escaped string.
+ * @example
+ *
+ * _.escape('fred, barney, & pebbles');
+ * // => 'fred, barney, &amp; pebbles'
+ */
+ function escape(string) {
+ string = toString(string);
+ return (string && reHasUnescapedHtml.test(string))
+ ? string.replace(reUnescapedHtml, escapeHtmlChar)
+ : string;
+ }
+
+ /**
+ * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
+ * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to escape.
+ * @returns {string} Returns the escaped string.
+ * @example
+ *
+ * _.escapeRegExp('[lodash](https://lodash.com/)');
+ * // => '\[lodash\]\(https://lodash\.com/\)'
+ */
+ function escapeRegExp(string) {
+ string = toString(string);
+ return (string && reHasRegExpChar.test(string))
+ ? string.replace(reRegExpChar, '\\$&')
+ : string;
+ }
+
+ /**
+ * Converts `string` to
+ * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the kebab cased string.
+ * @example
+ *
+ * _.kebabCase('Foo Bar');
+ * // => 'foo-bar'
+ *
+ * _.kebabCase('fooBar');
+ * // => 'foo-bar'
+ *
+ * _.kebabCase('__FOO_BAR__');
+ * // => 'foo-bar'
+ */
+ var kebabCase = createCompounder(function(result, word, index) {
+ return result + (index ? '-' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Converts `string`, as space separated words, to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the lower cased string.
+ * @example
+ *
+ * _.lowerCase('--Foo-Bar--');
+ * // => 'foo bar'
+ *
+ * _.lowerCase('fooBar');
+ * // => 'foo bar'
+ *
+ * _.lowerCase('__FOO_BAR__');
+ * // => 'foo bar'
+ */
+ var lowerCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Converts the first character of `string` to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the converted string.
+ * @example
+ *
+ * _.lowerFirst('Fred');
+ * // => 'fred'
+ *
+ * _.lowerFirst('FRED');
+ * // => 'fRED'
+ */
+ var lowerFirst = createCaseFirst('toLowerCase');
+
+ /**
+ * Pads `string` on the left and right sides if it's shorter than `length`.
+ * Padding characters are truncated if they can't be evenly divided by `length`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.pad('abc', 8);
+ * // => ' abc '
+ *
+ * _.pad('abc', 8, '_-');
+ * // => '_-abc_-_'
+ *
+ * _.pad('abc', 3);
+ * // => 'abc'
+ */
+ function pad(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+
+ var strLength = length ? stringSize(string) : 0;
+ if (!length || strLength >= length) {
+ return string;
+ }
+ var mid = (length - strLength) / 2;
+ return (
+ createPadding(nativeFloor(mid), chars) +
+ string +
+ createPadding(nativeCeil(mid), chars)
+ );
+ }
+
+ /**
+ * Pads `string` on the right side if it's shorter than `length`. Padding
+ * characters are truncated if they exceed `length`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.padEnd('abc', 6);
+ * // => 'abc '
+ *
+ * _.padEnd('abc', 6, '_-');
+ * // => 'abc_-_'
+ *
+ * _.padEnd('abc', 3);
+ * // => 'abc'
+ */
+ function padEnd(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+
+ var strLength = length ? stringSize(string) : 0;
+ return (length && strLength < length)
+ ? (string + createPadding(length - strLength, chars))
+ : string;
+ }
+
+ /**
+ * Pads `string` on the left side if it's shorter than `length`. Padding
+ * characters are truncated if they exceed `length`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.padStart('abc', 6);
+ * // => ' abc'
+ *
+ * _.padStart('abc', 6, '_-');
+ * // => '_-_abc'
+ *
+ * _.padStart('abc', 3);
+ * // => 'abc'
+ */
+ function padStart(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+
+ var strLength = length ? stringSize(string) : 0;
+ return (length && strLength < length)
+ ? (createPadding(length - strLength, chars) + string)
+ : string;
+ }
+
+ /**
+ * Converts `string` to an integer of the specified radix. If `radix` is
+ * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
+ * hexadecimal, in which case a `radix` of `16` is used.
+ *
+ * **Note:** This method aligns with the
+ * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category String
+ * @param {string} string The string to convert.
+ * @param {number} [radix=10] The radix to interpret `value` by.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.parseInt('08');
+ * // => 8
+ *
+ * _.map(['6', '08', '10'], _.parseInt);
+ * // => [6, 8, 10]
+ */
+ function parseInt(string, radix, guard) {
+ if (guard || radix == null) {
+ radix = 0;
+ } else if (radix) {
+ radix = +radix;
+ }
+ return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
+ }
+
+ /**
+ * Repeats the given string `n` times.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to repeat.
+ * @param {number} [n=1] The number of times to repeat the string.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {string} Returns the repeated string.
+ * @example
+ *
+ * _.repeat('*', 3);
+ * // => '***'
+ *
+ * _.repeat('abc', 2);
+ * // => 'abcabc'
+ *
+ * _.repeat('abc', 0);
+ * // => ''
+ */
+ function repeat(string, n, guard) {
+ if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
+ n = 1;
+ } else {
+ n = toInteger(n);
+ }
+ return baseRepeat(toString(string), n);
+ }
+
+ /**
+ * Replaces matches for `pattern` in `string` with `replacement`.
+ *
+ * **Note:** This method is based on
+ * [`String#replace`](https://mdn.io/String/replace).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to modify.
+ * @param {RegExp|string} pattern The pattern to replace.
+ * @param {Function|string} replacement The match replacement.
+ * @returns {string} Returns the modified string.
+ * @example
+ *
+ * _.replace('Hi Fred', 'Fred', 'Barney');
+ * // => 'Hi Barney'
+ */
+ function replace() {
+ var args = arguments,
+ string = toString(args[0]);
+
+ return args.length < 3 ? string : string.replace(args[1], args[2]);
+ }
+
+ /**
+ * Converts `string` to
+ * [snake case](https://en.wikipedia.org/wiki/Snake_case).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the snake cased string.
+ * @example
+ *
+ * _.snakeCase('Foo Bar');
+ * // => 'foo_bar'
+ *
+ * _.snakeCase('fooBar');
+ * // => 'foo_bar'
+ *
+ * _.snakeCase('--FOO-BAR--');
+ * // => 'foo_bar'
+ */
+ var snakeCase = createCompounder(function(result, word, index) {
+ return result + (index ? '_' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Splits `string` by `separator`.
+ *
+ * **Note:** This method is based on
+ * [`String#split`](https://mdn.io/String/split).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to split.
+ * @param {RegExp|string} separator The separator pattern to split by.
+ * @param {number} [limit] The length to truncate results to.
+ * @returns {Array} Returns the string segments.
+ * @example
+ *
+ * _.split('a-b-c', '-', 2);
+ * // => ['a', 'b']
+ */
+ function split(string, separator, limit) {
+ if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
+ separator = limit = undefined;
+ }
+ limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
+ if (!limit) {
+ return [];
+ }
+ string = toString(string);
+ if (string && (
+ typeof separator == 'string' ||
+ (separator != null && !isRegExp(separator))
+ )) {
+ separator = baseToString(separator);
+ if (!separator && hasUnicode(string)) {
+ return castSlice(stringToArray(string), 0, limit);
+ }
+ }
+ return string.split(separator, limit);
+ }
+
+ /**
+ * Converts `string` to
+ * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.1.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the start cased string.
+ * @example
+ *
+ * _.startCase('--foo-bar--');
+ * // => 'Foo Bar'
+ *
+ * _.startCase('fooBar');
+ * // => 'Foo Bar'
+ *
+ * _.startCase('__FOO_BAR__');
+ * // => 'FOO BAR'
+ */
+ var startCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + upperFirst(word);
+ });
+
+ /**
+ * Checks if `string` starts with the given target string.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to inspect.
+ * @param {string} [target] The string to search for.
+ * @param {number} [position=0] The position to search from.
+ * @returns {boolean} Returns `true` if `string` starts with `target`,
+ * else `false`.
+ * @example
+ *
+ * _.startsWith('abc', 'a');
+ * // => true
+ *
+ * _.startsWith('abc', 'b');
+ * // => false
+ *
+ * _.startsWith('abc', 'b', 1);
+ * // => true
+ */
+ function startsWith(string, target, position) {
+ string = toString(string);
+ position = position == null
+ ? 0
+ : baseClamp(toInteger(position), 0, string.length);
+
+ target = baseToString(target);
+ return string.slice(position, position + target.length) == target;
+ }
+
+ /**
+ * Creates a compiled template function that can interpolate data properties
+ * in "interpolate" delimiters, HTML-escape interpolated data properties in
+ * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
+ * properties may be accessed as free variables in the template. If a setting
+ * object is given, it takes precedence over `_.templateSettings` values.
+ *
+ * **Note:** In the development build `_.template` utilizes
+ * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
+ * for easier debugging.
+ *
+ * For more information on precompiling templates see
+ * [lodash's custom builds documentation](https://lodash.com/custom-builds).
+ *
+ * For more information on Chrome extension sandboxes see
+ * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The template string.
+ * @param {Object} [options={}] The options object.
+ * @param {RegExp} [options.escape=_.templateSettings.escape]
+ * The HTML "escape" delimiter.
+ * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
+ * The "evaluate" delimiter.
+ * @param {Object} [options.imports=_.templateSettings.imports]
+ * An object to import into the template as free variables.
+ * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
+ * The "interpolate" delimiter.
+ * @param {string} [options.sourceURL='lodash.templateSources[n]']
+ * The sourceURL of the compiled template.
+ * @param {string} [options.variable='obj']
+ * The data object variable name.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Function} Returns the compiled template function.
+ * @example
+ *
+ * // Use the "interpolate" delimiter to create a compiled template.
+ * var compiled = _.template('hello <%= user %>!');
+ * compiled({ 'user': 'fred' });
+ * // => 'hello fred!'
+ *
+ * // Use the HTML "escape" delimiter to escape data property values.
+ * var compiled = _.template('<b><%- value %></b>');
+ * compiled({ 'value': '<script>' });
+ * // => '<b>&lt;script&gt;</b>'
+ *
+ * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
+ * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
+ * compiled({ 'users': ['fred', 'barney'] });
+ * // => '<li>fred</li><li>barney</li>'
+ *
+ * // Use the internal `print` function in "evaluate" delimiters.
+ * var compiled = _.template('<% print("hello " + user); %>!');
+ * compiled({ 'user': 'barney' });
+ * // => 'hello barney!'
+ *
+ * // Use the ES template literal delimiter as an "interpolate" delimiter.
+ * // Disable support by replacing the "interpolate" delimiter.
+ * var compiled = _.template('hello ${ user }!');
+ * compiled({ 'user': 'pebbles' });
+ * // => 'hello pebbles!'
+ *
+ * // Use backslashes to treat delimiters as plain text.
+ * var compiled = _.template('<%= "\\<%- value %\\>" %>');
+ * compiled({ 'value': 'ignored' });
+ * // => '<%- value %>'
+ *
+ * // Use the `imports` option to import `jQuery` as `jq`.
+ * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
+ * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
+ * compiled({ 'users': ['fred', 'barney'] });
+ * // => '<li>fred</li><li>barney</li>'
+ *
+ * // Use the `sourceURL` option to specify a custom sourceURL for the template.
+ * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
+ * compiled(data);
+ * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
+ *
+ * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
+ * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
+ * compiled.source;
+ * // => function(data) {
+ * // var __t, __p = '';
+ * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
+ * // return __p;
+ * // }
+ *
+ * // Use custom template delimiters.
+ * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
+ * var compiled = _.template('hello {{ user }}!');
+ * compiled({ 'user': 'mustache' });
+ * // => 'hello mustache!'
+ *
+ * // Use the `source` property to inline compiled templates for meaningful
+ * // line numbers in error messages and stack traces.
+ * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
+ * var JST = {\
+ * "main": ' + _.template(mainText).source + '\
+ * };\
+ * ');
+ */
+ function template(string, options, guard) {
+ // Based on John Resig's `tmpl` implementation
+ // (http://ejohn.org/blog/javascript-micro-templating/)
+ // and Laura Doktorova's doT.js (https://github.com/olado/doT).
+ var settings = lodash.templateSettings;
+
+ if (guard && isIterateeCall(string, options, guard)) {
+ options = undefined;
+ }
+ string = toString(string);
+ options = assignInWith({}, options, settings, customDefaultsAssignIn);
+
+ var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
+ importsKeys = keys(imports),
+ importsValues = baseValues(imports, importsKeys);
+
+ var isEscaping,
+ isEvaluating,
+ index = 0,
+ interpolate = options.interpolate || reNoMatch,
+ source = "__p += '";
+
+ // Compile the regexp to match each delimiter.
+ var reDelimiters = RegExp(
+ (options.escape || reNoMatch).source + '|' +
+ interpolate.source + '|' +
+ (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+ (options.evaluate || reNoMatch).source + '|$'
+ , 'g');
+
+ // Use a sourceURL for easier debugging.
+ var sourceURL = '//# sourceURL=' +
+ ('sourceURL' in options
+ ? options.sourceURL
+ : ('lodash.templateSources[' + (++templateCounter) + ']')
+ ) + '\n';
+
+ string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+ interpolateValue || (interpolateValue = esTemplateValue);
+
+ // Escape characters that can't be included in string literals.
+ source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+ // Replace delimiters with snippets.
+ if (escapeValue) {
+ isEscaping = true;
+ source += "' +\n__e(" + escapeValue + ") +\n'";
+ }
+ if (evaluateValue) {
+ isEvaluating = true;
+ source += "';\n" + evaluateValue + ";\n__p += '";
+ }
+ if (interpolateValue) {
+ source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+ }
+ index = offset + match.length;
+
+ // The JS engine embedded in Adobe products needs `match` returned in
+ // order to produce the correct `offset` value.
+ return match;
+ });
+
+ source += "';\n";
+
+ // If `variable` is not specified wrap a with-statement around the generated
+ // code to add the data object to the top of the scope chain.
+ var variable = options.variable;
+ if (!variable) {
+ source = 'with (obj) {\n' + source + '\n}\n';
+ }
+ // Cleanup code by stripping empty strings.
+ source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+ .replace(reEmptyStringMiddle, '$1')
+ .replace(reEmptyStringTrailing, '$1;');
+
+ // Frame code as the function body.
+ source = 'function(' + (variable || 'obj') + ') {\n' +
+ (variable
+ ? ''
+ : 'obj || (obj = {});\n'
+ ) +
+ "var __t, __p = ''" +
+ (isEscaping
+ ? ', __e = _.escape'
+ : ''
+ ) +
+ (isEvaluating
+ ? ', __j = Array.prototype.join;\n' +
+ "function print() { __p += __j.call(arguments, '') }\n"
+ : ';\n'
+ ) +
+ source +
+ 'return __p\n}';
+
+ var result = attempt(function() {
+ return Function(importsKeys, sourceURL + 'return ' + source)
+ .apply(undefined, importsValues);
+ });
+
+ // Provide the compiled function's source by its `toString` method or
+ // the `source` property as a convenience for inlining compiled templates.
+ result.source = source;
+ if (isError(result)) {
+ throw result;
+ }
+ return result;
+ }
+
+ /**
+ * Converts `string`, as a whole, to lower case just like
+ * [String#toLowerCase](https://mdn.io/toLowerCase).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the lower cased string.
+ * @example
+ *
+ * _.toLower('--Foo-Bar--');
+ * // => '--foo-bar--'
+ *
+ * _.toLower('fooBar');
+ * // => 'foobar'
+ *
+ * _.toLower('__FOO_BAR__');
+ * // => '__foo_bar__'
+ */
+ function toLower(value) {
+ return toString(value).toLowerCase();
+ }
+
+ /**
+ * Converts `string`, as a whole, to upper case just like
+ * [String#toUpperCase](https://mdn.io/toUpperCase).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the upper cased string.
+ * @example
+ *
+ * _.toUpper('--foo-bar--');
+ * // => '--FOO-BAR--'
+ *
+ * _.toUpper('fooBar');
+ * // => 'FOOBAR'
+ *
+ * _.toUpper('__foo_bar__');
+ * // => '__FOO_BAR__'
+ */
+ function toUpper(value) {
+ return toString(value).toUpperCase();
+ }
+
+ /**
+ * Removes leading and trailing whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trim(' abc ');
+ * // => 'abc'
+ *
+ * _.trim('-_-abc-_-', '_-');
+ * // => 'abc'
+ *
+ * _.map([' foo ', ' bar '], _.trim);
+ * // => ['foo', 'bar']
+ */
+ function trim(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined)) {
+ return string.replace(reTrim, '');
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string),
+ chrSymbols = stringToArray(chars),
+ start = charsStartIndex(strSymbols, chrSymbols),
+ end = charsEndIndex(strSymbols, chrSymbols) + 1;
+
+ return castSlice(strSymbols, start, end).join('');
+ }
+
+ /**
+ * Removes trailing whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trimEnd(' abc ');
+ * // => ' abc'
+ *
+ * _.trimEnd('-_-abc-_-', '_-');
+ * // => '-_-abc'
+ */
+ function trimEnd(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined)) {
+ return string.replace(reTrimEnd, '');
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string),
+ end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
+
+ return castSlice(strSymbols, 0, end).join('');
+ }
+
+ /**
+ * Removes leading whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trimStart(' abc ');
+ * // => 'abc '
+ *
+ * _.trimStart('-_-abc-_-', '_-');
+ * // => 'abc-_-'
+ */
+ function trimStart(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined)) {
+ return string.replace(reTrimStart, '');
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string),
+ start = charsStartIndex(strSymbols, stringToArray(chars));
+
+ return castSlice(strSymbols, start).join('');
+ }
+
+ /**
+ * Truncates `string` if it's longer than the given maximum string length.
+ * The last characters of the truncated string are replaced with the omission
+ * string which defaults to "...".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to truncate.
+ * @param {Object} [options={}] The options object.
+ * @param {number} [options.length=30] The maximum string length.
+ * @param {string} [options.omission='...'] The string to indicate text is omitted.
+ * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
+ * @returns {string} Returns the truncated string.
+ * @example
+ *
+ * _.truncate('hi-diddly-ho there, neighborino');
+ * // => 'hi-diddly-ho there, neighbo...'
+ *
+ * _.truncate('hi-diddly-ho there, neighborino', {
+ * 'length': 24,
+ * 'separator': ' '
+ * });
+ * // => 'hi-diddly-ho there,...'
+ *
+ * _.truncate('hi-diddly-ho there, neighborino', {
+ * 'length': 24,
+ * 'separator': /,? +/
+ * });
+ * // => 'hi-diddly-ho there...'
+ *
+ * _.truncate('hi-diddly-ho there, neighborino', {
+ * 'omission': ' [...]'
+ * });
+ * // => 'hi-diddly-ho there, neig [...]'
+ */
+ function truncate(string, options) {
+ var length = DEFAULT_TRUNC_LENGTH,
+ omission = DEFAULT_TRUNC_OMISSION;
+
+ if (isObject(options)) {
+ var separator = 'separator' in options ? options.separator : separator;
+ length = 'length' in options ? toInteger(options.length) : length;
+ omission = 'omission' in options ? baseToString(options.omission) : omission;
+ }
+ string = toString(string);
+
+ var strLength = string.length;
+ if (hasUnicode(string)) {
+ var strSymbols = stringToArray(string);
+ strLength = strSymbols.length;
+ }
+ if (length >= strLength) {
+ return string;
+ }
+ var end = length - stringSize(omission);
+ if (end < 1) {
+ return omission;
+ }
+ var result = strSymbols
+ ? castSlice(strSymbols, 0, end).join('')
+ : string.slice(0, end);
+
+ if (separator === undefined) {
+ return result + omission;
+ }
+ if (strSymbols) {
+ end += (result.length - end);
+ }
+ if (isRegExp(separator)) {
+ if (string.slice(end).search(separator)) {
+ var match,
+ substring = result;
+
+ if (!separator.global) {
+ separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
+ }
+ separator.lastIndex = 0;
+ while ((match = separator.exec(substring))) {
+ var newEnd = match.index;
+ }
+ result = result.slice(0, newEnd === undefined ? end : newEnd);
+ }
+ } else if (string.indexOf(baseToString(separator), end) != end) {
+ var index = result.lastIndexOf(separator);
+ if (index > -1) {
+ result = result.slice(0, index);
+ }
+ }
+ return result + omission;
+ }
+
+ /**
+ * The inverse of `_.escape`; this method converts the HTML entities
+ * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
+ * their corresponding characters.
+ *
+ * **Note:** No other HTML entities are unescaped. To unescape additional
+ * HTML entities use a third-party library like [_he_](https://mths.be/he).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.6.0
+ * @category String
+ * @param {string} [string=''] The string to unescape.
+ * @returns {string} Returns the unescaped string.
+ * @example
+ *
+ * _.unescape('fred, barney, &amp; pebbles');
+ * // => 'fred, barney, & pebbles'
+ */
+ function unescape(string) {
+ string = toString(string);
+ return (string && reHasEscapedHtml.test(string))
+ ? string.replace(reEscapedHtml, unescapeHtmlChar)
+ : string;
+ }
+
+ /**
+ * Converts `string`, as space separated words, to upper case.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the upper cased string.
+ * @example
+ *
+ * _.upperCase('--foo-bar');
+ * // => 'FOO BAR'
+ *
+ * _.upperCase('fooBar');
+ * // => 'FOO BAR'
+ *
+ * _.upperCase('__foo_bar__');
+ * // => 'FOO BAR'
+ */
+ var upperCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + word.toUpperCase();
+ });
+
+ /**
+ * Converts the first character of `string` to upper case.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the converted string.
+ * @example
+ *
+ * _.upperFirst('fred');
+ * // => 'Fred'
+ *
+ * _.upperFirst('FRED');
+ * // => 'FRED'
+ */
+ var upperFirst = createCaseFirst('toUpperCase');
+
+ /**
+ * Splits `string` into an array of its words.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to inspect.
+ * @param {RegExp|string} [pattern] The pattern to match words.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the words of `string`.
+ * @example
+ *
+ * _.words('fred, barney, & pebbles');
+ * // => ['fred', 'barney', 'pebbles']
+ *
+ * _.words('fred, barney, & pebbles', /[^, ]+/g);
+ * // => ['fred', 'barney', '&', 'pebbles']
+ */
+ function words(string, pattern, guard) {
+ string = toString(string);
+ pattern = guard ? undefined : pattern;
+
+ if (pattern === undefined) {
+ return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
+ }
+ return string.match(pattern) || [];
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Attempts to invoke `func`, returning either the result or the caught error
+ * object. Any additional arguments are provided to `func` when it's invoked.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Util
+ * @param {Function} func The function to attempt.
+ * @param {...*} [args] The arguments to invoke `func` with.
+ * @returns {*} Returns the `func` result or error object.
+ * @example
+ *
+ * // Avoid throwing errors for invalid selectors.
+ * var elements = _.attempt(function(selector) {
+ * return document.querySelectorAll(selector);
+ * }, '>_>');
+ *
+ * if (_.isError(elements)) {
+ * elements = [];
+ * }
+ */
+ var attempt = baseRest(function(func, args) {
+ try {
+ return apply(func, undefined, args);
+ } catch (e) {
+ return isError(e) ? e : new Error(e);
+ }
+ });
+
+ /**
+ * Binds methods of an object to the object itself, overwriting the existing
+ * method.
+ *
+ * **Note:** This method doesn't set the "length" property of bound functions.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {Object} object The object to bind and assign the bound methods to.
+ * @param {...(string|string[])} methodNames The object method names to bind.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var view = {
+ * 'label': 'docs',
+ * 'click': function() {
+ * console.log('clicked ' + this.label);
+ * }
+ * };
+ *
+ * _.bindAll(view, ['click']);
+ * jQuery(element).on('click', view.click);
+ * // => Logs 'clicked docs' when clicked.
+ */
+ var bindAll = flatRest(function(object, methodNames) {
+ arrayEach(methodNames, function(key) {
+ key = toKey(key);
+ baseAssignValue(object, key, bind(object[key], object));
+ });
+ return object;
+ });
+
+ /**
+ * Creates a function that iterates over `pairs` and invokes the corresponding
+ * function of the first predicate to return truthy. The predicate-function
+ * pairs are invoked with the `this` binding and arguments of the created
+ * function.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Util
+ * @param {Array} pairs The predicate-function pairs.
+ * @returns {Function} Returns the new composite function.
+ * @example
+ *
+ * var func = _.cond([
+ * [_.matches({ 'a': 1 }), _.constant('matches A')],
+ * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
+ * [_.stubTrue, _.constant('no match')]
+ * ]);
+ *
+ * func({ 'a': 1, 'b': 2 });
+ * // => 'matches A'
+ *
+ * func({ 'a': 0, 'b': 1 });
+ * // => 'matches B'
+ *
+ * func({ 'a': '1', 'b': '2' });
+ * // => 'no match'
+ */
+ function cond(pairs) {
+ var length = pairs == null ? 0 : pairs.length,
+ toIteratee = getIteratee();
+
+ pairs = !length ? [] : arrayMap(pairs, function(pair) {
+ if (typeof pair[1] != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return [toIteratee(pair[0]), pair[1]];
+ });
+
+ return baseRest(function(args) {
+ var index = -1;
+ while (++index < length) {
+ var pair = pairs[index];
+ if (apply(pair[0], this, args)) {
+ return apply(pair[1], this, args);
+ }
+ }
+ });
+ }
+
+ /**
+ * Creates a function that invokes the predicate properties of `source` with
+ * the corresponding property values of a given object, returning `true` if
+ * all predicates return truthy, else `false`.
+ *
+ * **Note:** The created function is equivalent to `_.conformsTo` with
+ * `source` partially applied.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Util
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {Function} Returns the new spec function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': 2, 'b': 1 },
+ * { 'a': 1, 'b': 2 }
+ * ];
+ *
+ * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
+ * // => [{ 'a': 1, 'b': 2 }]
+ */
+ function conforms(source) {
+ return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
+ }
+
+ /**
+ * Creates a function that returns `value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Util
+ * @param {*} value The value to return from the new function.
+ * @returns {Function} Returns the new constant function.
+ * @example
+ *
+ * var objects = _.times(2, _.constant({ 'a': 1 }));
+ *
+ * console.log(objects);
+ * // => [{ 'a': 1 }, { 'a': 1 }]
+ *
+ * console.log(objects[0] === objects[1]);
+ * // => true
+ */
+ function constant(value) {
+ return function() {
+ return value;
+ };
+ }
+
+ /**
+ * Checks `value` to determine whether a default value should be returned in
+ * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
+ * or `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.14.0
+ * @category Util
+ * @param {*} value The value to check.
+ * @param {*} defaultValue The default value.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * _.defaultTo(1, 10);
+ * // => 1
+ *
+ * _.defaultTo(undefined, 10);
+ * // => 10
+ */
+ function defaultTo(value, defaultValue) {
+ return (value == null || value !== value) ? defaultValue : value;
+ }
+
+ /**
+ * Creates a function that returns the result of invoking the given functions
+ * with the `this` binding of the created function, where each successive
+ * invocation is supplied the return value of the previous.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Util
+ * @param {...(Function|Function[])} [funcs] The functions to invoke.
+ * @returns {Function} Returns the new composite function.
+ * @see _.flowRight
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var addSquare = _.flow([_.add, square]);
+ * addSquare(1, 2);
+ * // => 9
+ */
+ var flow = createFlow();
+
+ /**
+ * This method is like `_.flow` except that it creates a function that
+ * invokes the given functions from right to left.
+ *
+ * @static
+ * @since 3.0.0
+ * @memberOf _
+ * @category Util
+ * @param {...(Function|Function[])} [funcs] The functions to invoke.
+ * @returns {Function} Returns the new composite function.
+ * @see _.flow
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var addSquare = _.flowRight([square, _.add]);
+ * addSquare(1, 2);
+ * // => 9
+ */
+ var flowRight = createFlow(true);
+
+ /**
+ * This method returns the first argument it receives.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {*} value Any value.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * var object = { 'a': 1 };
+ *
+ * console.log(_.identity(object) === object);
+ * // => true
+ */
+ function identity(value) {
+ return value;
+ }
+
+ /**
+ * Creates a function that invokes `func` with the arguments of the created
+ * function. If `func` is a property name, the created function returns the
+ * property value for a given element. If `func` is an array or object, the
+ * created function returns `true` for elements that contain the equivalent
+ * source properties, otherwise it returns `false`.
+ *
+ * @static
+ * @since 4.0.0
+ * @memberOf _
+ * @category Util
+ * @param {*} [func=_.identity] The value to convert to a callback.
+ * @returns {Function} Returns the callback.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
+ * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.filter(users, _.iteratee(['user', 'fred']));
+ * // => [{ 'user': 'fred', 'age': 40 }]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.map(users, _.iteratee('user'));
+ * // => ['barney', 'fred']
+ *
+ * // Create custom iteratee shorthands.
+ * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
+ * return !_.isRegExp(func) ? iteratee(func) : function(string) {
+ * return func.test(string);
+ * };
+ * });
+ *
+ * _.filter(['abc', 'def'], /ef/);
+ * // => ['def']
+ */
+ function iteratee(func) {
+ return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
+ }
+
+ /**
+ * Creates a function that performs a partial deep comparison between a given
+ * object and `source`, returning `true` if the given object has equivalent
+ * property values, else `false`.
+ *
+ * **Note:** The created function is equivalent to `_.isMatch` with `source`
+ * partially applied.
+ *
+ * Partial comparisons will match empty array and empty object `source`
+ * values against any array or object value, respectively. See `_.isEqual`
+ * for a list of supported value comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Util
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new spec function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': 1, 'b': 2, 'c': 3 },
+ * { 'a': 4, 'b': 5, 'c': 6 }
+ * ];
+ *
+ * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
+ * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
+ */
+ function matches(source) {
+ return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
+ }
+
+ /**
+ * Creates a function that performs a partial deep comparison between the
+ * value at `path` of a given object to `srcValue`, returning `true` if the
+ * object value is equivalent, else `false`.
+ *
+ * **Note:** Partial comparisons will match empty array and empty object
+ * `srcValue` values against any array or object value, respectively. See
+ * `_.isEqual` for a list of supported value comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.2.0
+ * @category Util
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new spec function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': 1, 'b': 2, 'c': 3 },
+ * { 'a': 4, 'b': 5, 'c': 6 }
+ * ];
+ *
+ * _.find(objects, _.matchesProperty('a', 4));
+ * // => { 'a': 4, 'b': 5, 'c': 6 }
+ */
+ function matchesProperty(path, srcValue) {
+ return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
+ }
+
+ /**
+ * Creates a function that invokes the method at `path` of a given object.
+ * Any additional arguments are provided to the invoked method.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.7.0
+ * @category Util
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {Function} Returns the new invoker function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': { 'b': _.constant(2) } },
+ * { 'a': { 'b': _.constant(1) } }
+ * ];
+ *
+ * _.map(objects, _.method('a.b'));
+ * // => [2, 1]
+ *
+ * _.map(objects, _.method(['a', 'b']));
+ * // => [2, 1]
+ */
+ var method = baseRest(function(path, args) {
+ return function(object) {
+ return baseInvoke(object, path, args);
+ };
+ });
+
+ /**
+ * The opposite of `_.method`; this method creates a function that invokes
+ * the method at a given path of `object`. Any additional arguments are
+ * provided to the invoked method.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.7.0
+ * @category Util
+ * @param {Object} object The object to query.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {Function} Returns the new invoker function.
+ * @example
+ *
+ * var array = _.times(3, _.constant),
+ * object = { 'a': array, 'b': array, 'c': array };
+ *
+ * _.map(['a[2]', 'c[0]'], _.methodOf(object));
+ * // => [2, 0]
+ *
+ * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
+ * // => [2, 0]
+ */
+ var methodOf = baseRest(function(object, args) {
+ return function(path) {
+ return baseInvoke(object, path, args);
+ };
+ });
+
+ /**
+ * Adds all own enumerable string keyed function properties of a source
+ * object to the destination object. If `object` is a function, then methods
+ * are added to its prototype as well.
+ *
+ * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
+ * avoid conflicts caused by modifying the original.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {Function|Object} [object=lodash] The destination object.
+ * @param {Object} source The object of functions to add.
+ * @param {Object} [options={}] The options object.
+ * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
+ * @returns {Function|Object} Returns `object`.
+ * @example
+ *
+ * function vowels(string) {
+ * return _.filter(string, function(v) {
+ * return /[aeiou]/i.test(v);
+ * });
+ * }
+ *
+ * _.mixin({ 'vowels': vowels });
+ * _.vowels('fred');
+ * // => ['e']
+ *
+ * _('fred').vowels().value();
+ * // => ['e']
+ *
+ * _.mixin({ 'vowels': vowels }, { 'chain': false });
+ * _('fred').vowels();
+ * // => ['e']
+ */
+ function mixin(object, source, options) {
+ var props = keys(source),
+ methodNames = baseFunctions(source, props);
+
+ if (options == null &&
+ !(isObject(source) && (methodNames.length || !props.length))) {
+ options = source;
+ source = object;
+ object = this;
+ methodNames = baseFunctions(source, keys(source));
+ }
+ var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
+ isFunc = isFunction(object);
+
+ arrayEach(methodNames, function(methodName) {
+ var func = source[methodName];
+ object[methodName] = func;
+ if (isFunc) {
+ object.prototype[methodName] = function() {
+ var chainAll = this.__chain__;
+ if (chain || chainAll) {
+ var result = object(this.__wrapped__),
+ actions = result.__actions__ = copyArray(this.__actions__);
+
+ actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
+ result.__chain__ = chainAll;
+ return result;
+ }
+ return func.apply(object, arrayPush([this.value()], arguments));
+ };
+ }
+ });
+
+ return object;
+ }
+
+ /**
+ * Reverts the `_` variable to its previous value and returns a reference to
+ * the `lodash` function.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @returns {Function} Returns the `lodash` function.
+ * @example
+ *
+ * var lodash = _.noConflict();
+ */
+ function noConflict() {
+ if (root._ === this) {
+ root._ = oldDash;
+ }
+ return this;
+ }
+
+ /**
+ * This method returns `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.3.0
+ * @category Util
+ * @example
+ *
+ * _.times(2, _.noop);
+ * // => [undefined, undefined]
+ */
+ function noop() {
+ // No operation performed.
+ }
+
+ /**
+ * Creates a function that gets the argument at index `n`. If `n` is negative,
+ * the nth argument from the end is returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Util
+ * @param {number} [n=0] The index of the argument to return.
+ * @returns {Function} Returns the new pass-thru function.
+ * @example
+ *
+ * var func = _.nthArg(1);
+ * func('a', 'b', 'c', 'd');
+ * // => 'b'
+ *
+ * var func = _.nthArg(-2);
+ * func('a', 'b', 'c', 'd');
+ * // => 'c'
+ */
+ function nthArg(n) {
+ n = toInteger(n);
+ return baseRest(function(args) {
+ return baseNth(args, n);
+ });
+ }
+
+ /**
+ * Creates a function that invokes `iteratees` with the arguments it receives
+ * and returns their results.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Util
+ * @param {...(Function|Function[])} [iteratees=[_.identity]]
+ * The iteratees to invoke.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var func = _.over([Math.max, Math.min]);
+ *
+ * func(1, 2, 3, 4);
+ * // => [4, 1]
+ */
+ var over = createOver(arrayMap);
+
+ /**
+ * Creates a function that checks if **all** of the `predicates` return
+ * truthy when invoked with the arguments it receives.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Util
+ * @param {...(Function|Function[])} [predicates=[_.identity]]
+ * The predicates to check.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var func = _.overEvery([Boolean, isFinite]);
+ *
+ * func('1');
+ * // => true
+ *
+ * func(null);
+ * // => false
+ *
+ * func(NaN);
+ * // => false
+ */
+ var overEvery = createOver(arrayEvery);
+
+ /**
+ * Creates a function that checks if **any** of the `predicates` return
+ * truthy when invoked with the arguments it receives.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Util
+ * @param {...(Function|Function[])} [predicates=[_.identity]]
+ * The predicates to check.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var func = _.overSome([Boolean, isFinite]);
+ *
+ * func('1');
+ * // => true
+ *
+ * func(null);
+ * // => true
+ *
+ * func(NaN);
+ * // => false
+ */
+ var overSome = createOver(arraySome);
+
+ /**
+ * Creates a function that returns the value at `path` of a given object.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Util
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new accessor function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': { 'b': 2 } },
+ * { 'a': { 'b': 1 } }
+ * ];
+ *
+ * _.map(objects, _.property('a.b'));
+ * // => [2, 1]
+ *
+ * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
+ * // => [1, 2]
+ */
+ function property(path) {
+ return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
+ }
+
+ /**
+ * The opposite of `_.property`; this method creates a function that returns
+ * the value at a given path of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Util
+ * @param {Object} object The object to query.
+ * @returns {Function} Returns the new accessor function.
+ * @example
+ *
+ * var array = [0, 1, 2],
+ * object = { 'a': array, 'b': array, 'c': array };
+ *
+ * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
+ * // => [2, 0]
+ *
+ * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
+ * // => [2, 0]
+ */
+ function propertyOf(object) {
+ return function(path) {
+ return object == null ? undefined : baseGet(object, path);
+ };
+ }
+
+ /**
+ * Creates an array of numbers (positive and/or negative) progressing from
+ * `start` up to, but not including, `end`. A step of `-1` is used if a negative
+ * `start` is specified without an `end` or `step`. If `end` is not specified,
+ * it's set to `start` with `start` then set to `0`.
+ *
+ * **Note:** JavaScript follows the IEEE-754 standard for resolving
+ * floating-point values which can produce unexpected results.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} [step=1] The value to increment or decrement by.
+ * @returns {Array} Returns the range of numbers.
+ * @see _.inRange, _.rangeRight
+ * @example
+ *
+ * _.range(4);
+ * // => [0, 1, 2, 3]
+ *
+ * _.range(-4);
+ * // => [0, -1, -2, -3]
+ *
+ * _.range(1, 5);
+ * // => [1, 2, 3, 4]
+ *
+ * _.range(0, 20, 5);
+ * // => [0, 5, 10, 15]
+ *
+ * _.range(0, -4, -1);
+ * // => [0, -1, -2, -3]
+ *
+ * _.range(1, 4, 0);
+ * // => [1, 1, 1]
+ *
+ * _.range(0);
+ * // => []
+ */
+ var range = createRange();
+
+ /**
+ * This method is like `_.range` except that it populates values in
+ * descending order.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Util
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} [step=1] The value to increment or decrement by.
+ * @returns {Array} Returns the range of numbers.
+ * @see _.inRange, _.range
+ * @example
+ *
+ * _.rangeRight(4);
+ * // => [3, 2, 1, 0]
+ *
+ * _.rangeRight(-4);
+ * // => [-3, -2, -1, 0]
+ *
+ * _.rangeRight(1, 5);
+ * // => [4, 3, 2, 1]
+ *
+ * _.rangeRight(0, 20, 5);
+ * // => [15, 10, 5, 0]
+ *
+ * _.rangeRight(0, -4, -1);
+ * // => [-3, -2, -1, 0]
+ *
+ * _.rangeRight(1, 4, 0);
+ * // => [1, 1, 1]
+ *
+ * _.rangeRight(0);
+ * // => []
+ */
+ var rangeRight = createRange(true);
+
+ /**
+ * This method returns a new empty array.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {Array} Returns the new empty array.
+ * @example
+ *
+ * var arrays = _.times(2, _.stubArray);
+ *
+ * console.log(arrays);
+ * // => [[], []]
+ *
+ * console.log(arrays[0] === arrays[1]);
+ * // => false
+ */
+ function stubArray() {
+ return [];
+ }
+
+ /**
+ * This method returns `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {boolean} Returns `false`.
+ * @example
+ *
+ * _.times(2, _.stubFalse);
+ * // => [false, false]
+ */
+ function stubFalse() {
+ return false;
+ }
+
+ /**
+ * This method returns a new empty object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {Object} Returns the new empty object.
+ * @example
+ *
+ * var objects = _.times(2, _.stubObject);
+ *
+ * console.log(objects);
+ * // => [{}, {}]
+ *
+ * console.log(objects[0] === objects[1]);
+ * // => false
+ */
+ function stubObject() {
+ return {};
+ }
+
+ /**
+ * This method returns an empty string.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {string} Returns the empty string.
+ * @example
+ *
+ * _.times(2, _.stubString);
+ * // => ['', '']
+ */
+ function stubString() {
+ return '';
+ }
+
+ /**
+ * This method returns `true`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {boolean} Returns `true`.
+ * @example
+ *
+ * _.times(2, _.stubTrue);
+ * // => [true, true]
+ */
+ function stubTrue() {
+ return true;
+ }
+
+ /**
+ * Invokes the iteratee `n` times, returning an array of the results of
+ * each invocation. The iteratee is invoked with one argument; (index).
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the array of results.
+ * @example
+ *
+ * _.times(3, String);
+ * // => ['0', '1', '2']
+ *
+ * _.times(4, _.constant(0));
+ * // => [0, 0, 0, 0]
+ */
+ function times(n, iteratee) {
+ n = toInteger(n);
+ if (n < 1 || n > MAX_SAFE_INTEGER) {
+ return [];
+ }
+ var index = MAX_ARRAY_LENGTH,
+ length = nativeMin(n, MAX_ARRAY_LENGTH);
+
+ iteratee = getIteratee(iteratee);
+ n -= MAX_ARRAY_LENGTH;
+
+ var result = baseTimes(length, iteratee);
+ while (++index < n) {
+ iteratee(index);
+ }
+ return result;
+ }
+
+ /**
+ * Converts `value` to a property path array.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Util
+ * @param {*} value The value to convert.
+ * @returns {Array} Returns the new property path array.
+ * @example
+ *
+ * _.toPath('a.b.c');
+ * // => ['a', 'b', 'c']
+ *
+ * _.toPath('a[0].b.c');
+ * // => ['a', '0', 'b', 'c']
+ */
+ function toPath(value) {
+ if (isArray(value)) {
+ return arrayMap(value, toKey);
+ }
+ return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
+ }
+
+ /**
+ * Generates a unique ID. If `prefix` is given, the ID is appended to it.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {string} [prefix=''] The value to prefix the ID with.
+ * @returns {string} Returns the unique ID.
+ * @example
+ *
+ * _.uniqueId('contact_');
+ * // => 'contact_104'
+ *
+ * _.uniqueId();
+ * // => '105'
+ */
+ function uniqueId(prefix) {
+ var id = ++idCounter;
+ return toString(prefix) + id;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Adds two numbers.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.4.0
+ * @category Math
+ * @param {number} augend The first number in an addition.
+ * @param {number} addend The second number in an addition.
+ * @returns {number} Returns the total.
+ * @example
+ *
+ * _.add(6, 4);
+ * // => 10
+ */
+ var add = createMathOperation(function(augend, addend) {
+ return augend + addend;
+ }, 0);
+
+ /**
+ * Computes `number` rounded up to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.10.0
+ * @category Math
+ * @param {number} number The number to round up.
+ * @param {number} [precision=0] The precision to round up to.
+ * @returns {number} Returns the rounded up number.
+ * @example
+ *
+ * _.ceil(4.006);
+ * // => 5
+ *
+ * _.ceil(6.004, 2);
+ * // => 6.01
+ *
+ * _.ceil(6040, -2);
+ * // => 6100
+ */
+ var ceil = createRound('ceil');
+
+ /**
+ * Divide two numbers.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.7.0
+ * @category Math
+ * @param {number} dividend The first number in a division.
+ * @param {number} divisor The second number in a division.
+ * @returns {number} Returns the quotient.
+ * @example
+ *
+ * _.divide(6, 4);
+ * // => 1.5
+ */
+ var divide = createMathOperation(function(dividend, divisor) {
+ return dividend / divisor;
+ }, 1);
+
+ /**
+ * Computes `number` rounded down to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.10.0
+ * @category Math
+ * @param {number} number The number to round down.
+ * @param {number} [precision=0] The precision to round down to.
+ * @returns {number} Returns the rounded down number.
+ * @example
+ *
+ * _.floor(4.006);
+ * // => 4
+ *
+ * _.floor(0.046, 2);
+ * // => 0.04
+ *
+ * _.floor(4060, -2);
+ * // => 4000
+ */
+ var floor = createRound('floor');
+
+ /**
+ * Computes the maximum value of `array`. If `array` is empty or falsey,
+ * `undefined` is returned.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {*} Returns the maximum value.
+ * @example
+ *
+ * _.max([4, 2, 8, 6]);
+ * // => 8
+ *
+ * _.max([]);
+ * // => undefined
+ */
+ function max(array) {
+ return (array && array.length)
+ ? baseExtremum(array, identity, baseGt)
+ : undefined;
+ }
+
+ /**
+ * This method is like `_.max` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the criterion by which
+ * the value is ranked. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {*} Returns the maximum value.
+ * @example
+ *
+ * var objects = [{ 'n': 1 }, { 'n': 2 }];
+ *
+ * _.maxBy(objects, function(o) { return o.n; });
+ * // => { 'n': 2 }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.maxBy(objects, 'n');
+ * // => { 'n': 2 }
+ */
+ function maxBy(array, iteratee) {
+ return (array && array.length)
+ ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
+ : undefined;
+ }
+
+ /**
+ * Computes the mean of the values in `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {number} Returns the mean.
+ * @example
+ *
+ * _.mean([4, 2, 8, 6]);
+ * // => 5
+ */
+ function mean(array) {
+ return baseMean(array, identity);
+ }
+
+ /**
+ * This method is like `_.mean` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the value to be averaged.
+ * The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.7.0
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the mean.
+ * @example
+ *
+ * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
+ *
+ * _.meanBy(objects, function(o) { return o.n; });
+ * // => 5
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.meanBy(objects, 'n');
+ * // => 5
+ */
+ function meanBy(array, iteratee) {
+ return baseMean(array, getIteratee(iteratee, 2));
+ }
+
+ /**
+ * Computes the minimum value of `array`. If `array` is empty or falsey,
+ * `undefined` is returned.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {*} Returns the minimum value.
+ * @example
+ *
+ * _.min([4, 2, 8, 6]);
+ * // => 2
+ *
+ * _.min([]);
+ * // => undefined
+ */
+ function min(array) {
+ return (array && array.length)
+ ? baseExtremum(array, identity, baseLt)
+ : undefined;
+ }
+
+ /**
+ * This method is like `_.min` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the criterion by which
+ * the value is ranked. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {*} Returns the minimum value.
+ * @example
+ *
+ * var objects = [{ 'n': 1 }, { 'n': 2 }];
+ *
+ * _.minBy(objects, function(o) { return o.n; });
+ * // => { 'n': 1 }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.minBy(objects, 'n');
+ * // => { 'n': 1 }
+ */
+ function minBy(array, iteratee) {
+ return (array && array.length)
+ ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
+ : undefined;
+ }
+
+ /**
+ * Multiply two numbers.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.7.0
+ * @category Math
+ * @param {number} multiplier The first number in a multiplication.
+ * @param {number} multiplicand The second number in a multiplication.
+ * @returns {number} Returns the product.
+ * @example
+ *
+ * _.multiply(6, 4);
+ * // => 24
+ */
+ var multiply = createMathOperation(function(multiplier, multiplicand) {
+ return multiplier * multiplicand;
+ }, 1);
+
+ /**
+ * Computes `number` rounded to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.10.0
+ * @category Math
+ * @param {number} number The number to round.
+ * @param {number} [precision=0] The precision to round to.
+ * @returns {number} Returns the rounded number.
+ * @example
+ *
+ * _.round(4.006);
+ * // => 4
+ *
+ * _.round(4.006, 2);
+ * // => 4.01
+ *
+ * _.round(4060, -2);
+ * // => 4100
+ */
+ var round = createRound('round');
+
+ /**
+ * Subtract two numbers.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Math
+ * @param {number} minuend The first number in a subtraction.
+ * @param {number} subtrahend The second number in a subtraction.
+ * @returns {number} Returns the difference.
+ * @example
+ *
+ * _.subtract(6, 4);
+ * // => 2
+ */
+ var subtract = createMathOperation(function(minuend, subtrahend) {
+ return minuend - subtrahend;
+ }, 0);
+
+ /**
+ * Computes the sum of the values in `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.4.0
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {number} Returns the sum.
+ * @example
+ *
+ * _.sum([4, 2, 8, 6]);
+ * // => 20
+ */
+ function sum(array) {
+ return (array && array.length)
+ ? baseSum(array, identity)
+ : 0;
+ }
+
+ /**
+ * This method is like `_.sum` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the value to be summed.
+ * The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the sum.
+ * @example
+ *
+ * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
+ *
+ * _.sumBy(objects, function(o) { return o.n; });
+ * // => 20
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.sumBy(objects, 'n');
+ * // => 20
+ */
+ function sumBy(array, iteratee) {
+ return (array && array.length)
+ ? baseSum(array, getIteratee(iteratee, 2))
+ : 0;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ // Add methods that return wrapped values in chain sequences.
+ lodash.after = after;
+ lodash.ary = ary;
+ lodash.assign = assign;
+ lodash.assignIn = assignIn;
+ lodash.assignInWith = assignInWith;
+ lodash.assignWith = assignWith;
+ lodash.at = at;
+ lodash.before = before;
+ lodash.bind = bind;
+ lodash.bindAll = bindAll;
+ lodash.bindKey = bindKey;
+ lodash.castArray = castArray;
+ lodash.chain = chain;
+ lodash.chunk = chunk;
+ lodash.compact = compact;
+ lodash.concat = concat;
+ lodash.cond = cond;
+ lodash.conforms = conforms;
+ lodash.constant = constant;
+ lodash.countBy = countBy;
+ lodash.create = create;
+ lodash.curry = curry;
+ lodash.curryRight = curryRight;
+ lodash.debounce = debounce;
+ lodash.defaults = defaults;
+ lodash.defaultsDeep = defaultsDeep;
+ lodash.defer = defer;
+ lodash.delay = delay;
+ lodash.difference = difference;
+ lodash.differenceBy = differenceBy;
+ lodash.differenceWith = differenceWith;
+ lodash.drop = drop;
+ lodash.dropRight = dropRight;
+ lodash.dropRightWhile = dropRightWhile;
+ lodash.dropWhile = dropWhile;
+ lodash.fill = fill;
+ lodash.filter = filter;
+ lodash.flatMap = flatMap;
+ lodash.flatMapDeep = flatMapDeep;
+ lodash.flatMapDepth = flatMapDepth;
+ lodash.flatten = flatten;
+ lodash.flattenDeep = flattenDeep;
+ lodash.flattenDepth = flattenDepth;
+ lodash.flip = flip;
+ lodash.flow = flow;
+ lodash.flowRight = flowRight;
+ lodash.fromPairs = fromPairs;
+ lodash.functions = functions;
+ lodash.functionsIn = functionsIn;
+ lodash.groupBy = groupBy;
+ lodash.initial = initial;
+ lodash.intersection = intersection;
+ lodash.intersectionBy = intersectionBy;
+ lodash.intersectionWith = intersectionWith;
+ lodash.invert = invert;
+ lodash.invertBy = invertBy;
+ lodash.invokeMap = invokeMap;
+ lodash.iteratee = iteratee;
+ lodash.keyBy = keyBy;
+ lodash.keys = keys;
+ lodash.keysIn = keysIn;
+ lodash.map = map;
+ lodash.mapKeys = mapKeys;
+ lodash.mapValues = mapValues;
+ lodash.matches = matches;
+ lodash.matchesProperty = matchesProperty;
+ lodash.memoize = memoize;
+ lodash.merge = merge;
+ lodash.mergeWith = mergeWith;
+ lodash.method = method;
+ lodash.methodOf = methodOf;
+ lodash.mixin = mixin;
+ lodash.negate = negate;
+ lodash.nthArg = nthArg;
+ lodash.omit = omit;
+ lodash.omitBy = omitBy;
+ lodash.once = once;
+ lodash.orderBy = orderBy;
+ lodash.over = over;
+ lodash.overArgs = overArgs;
+ lodash.overEvery = overEvery;
+ lodash.overSome = overSome;
+ lodash.partial = partial;
+ lodash.partialRight = partialRight;
+ lodash.partition = partition;
+ lodash.pick = pick;
+ lodash.pickBy = pickBy;
+ lodash.property = property;
+ lodash.propertyOf = propertyOf;
+ lodash.pull = pull;
+ lodash.pullAll = pullAll;
+ lodash.pullAllBy = pullAllBy;
+ lodash.pullAllWith = pullAllWith;
+ lodash.pullAt = pullAt;
+ lodash.range = range;
+ lodash.rangeRight = rangeRight;
+ lodash.rearg = rearg;
+ lodash.reject = reject;
+ lodash.remove = remove;
+ lodash.rest = rest;
+ lodash.reverse = reverse;
+ lodash.sampleSize = sampleSize;
+ lodash.set = set;
+ lodash.setWith = setWith;
+ lodash.shuffle = shuffle;
+ lodash.slice = slice;
+ lodash.sortBy = sortBy;
+ lodash.sortedUniq = sortedUniq;
+ lodash.sortedUniqBy = sortedUniqBy;
+ lodash.split = split;
+ lodash.spread = spread;
+ lodash.tail = tail;
+ lodash.take = take;
+ lodash.takeRight = takeRight;
+ lodash.takeRightWhile = takeRightWhile;
+ lodash.takeWhile = takeWhile;
+ lodash.tap = tap;
+ lodash.throttle = throttle;
+ lodash.thru = thru;
+ lodash.toArray = toArray;
+ lodash.toPairs = toPairs;
+ lodash.toPairsIn = toPairsIn;
+ lodash.toPath = toPath;
+ lodash.toPlainObject = toPlainObject;
+ lodash.transform = transform;
+ lodash.unary = unary;
+ lodash.union = union;
+ lodash.unionBy = unionBy;
+ lodash.unionWith = unionWith;
+ lodash.uniq = uniq;
+ lodash.uniqBy = uniqBy;
+ lodash.uniqWith = uniqWith;
+ lodash.unset = unset;
+ lodash.unzip = unzip;
+ lodash.unzipWith = unzipWith;
+ lodash.update = update;
+ lodash.updateWith = updateWith;
+ lodash.values = values;
+ lodash.valuesIn = valuesIn;
+ lodash.without = without;
+ lodash.words = words;
+ lodash.wrap = wrap;
+ lodash.xor = xor;
+ lodash.xorBy = xorBy;
+ lodash.xorWith = xorWith;
+ lodash.zip = zip;
+ lodash.zipObject = zipObject;
+ lodash.zipObjectDeep = zipObjectDeep;
+ lodash.zipWith = zipWith;
+
+ // Add aliases.
+ lodash.entries = toPairs;
+ lodash.entriesIn = toPairsIn;
+ lodash.extend = assignIn;
+ lodash.extendWith = assignInWith;
+
+ // Add methods to `lodash.prototype`.
+ mixin(lodash, lodash);
+
+ /*------------------------------------------------------------------------*/
+
+ // Add methods that return unwrapped values in chain sequences.
+ lodash.add = add;
+ lodash.attempt = attempt;
+ lodash.camelCase = camelCase;
+ lodash.capitalize = capitalize;
+ lodash.ceil = ceil;
+ lodash.clamp = clamp;
+ lodash.clone = clone;
+ lodash.cloneDeep = cloneDeep;
+ lodash.cloneDeepWith = cloneDeepWith;
+ lodash.cloneWith = cloneWith;
+ lodash.conformsTo = conformsTo;
+ lodash.deburr = deburr;
+ lodash.defaultTo = defaultTo;
+ lodash.divide = divide;
+ lodash.endsWith = endsWith;
+ lodash.eq = eq;
+ lodash.escape = escape;
+ lodash.escapeRegExp = escapeRegExp;
+ lodash.every = every;
+ lodash.find = find;
+ lodash.findIndex = findIndex;
+ lodash.findKey = findKey;
+ lodash.findLast = findLast;
+ lodash.findLastIndex = findLastIndex;
+ lodash.findLastKey = findLastKey;
+ lodash.floor = floor;
+ lodash.forEach = forEach;
+ lodash.forEachRight = forEachRight;
+ lodash.forIn = forIn;
+ lodash.forInRight = forInRight;
+ lodash.forOwn = forOwn;
+ lodash.forOwnRight = forOwnRight;
+ lodash.get = get;
+ lodash.gt = gt;
+ lodash.gte = gte;
+ lodash.has = has;
+ lodash.hasIn = hasIn;
+ lodash.head = head;
+ lodash.identity = identity;
+ lodash.includes = includes;
+ lodash.indexOf = indexOf;
+ lodash.inRange = inRange;
+ lodash.invoke = invoke;
+ lodash.isArguments = isArguments;
+ lodash.isArray = isArray;
+ lodash.isArrayBuffer = isArrayBuffer;
+ lodash.isArrayLike = isArrayLike;
+ lodash.isArrayLikeObject = isArrayLikeObject;
+ lodash.isBoolean = isBoolean;
+ lodash.isBuffer = isBuffer;
+ lodash.isDate = isDate;
+ lodash.isElement = isElement;
+ lodash.isEmpty = isEmpty;
+ lodash.isEqual = isEqual;
+ lodash.isEqualWith = isEqualWith;
+ lodash.isError = isError;
+ lodash.isFinite = isFinite;
+ lodash.isFunction = isFunction;
+ lodash.isInteger = isInteger;
+ lodash.isLength = isLength;
+ lodash.isMap = isMap;
+ lodash.isMatch = isMatch;
+ lodash.isMatchWith = isMatchWith;
+ lodash.isNaN = isNaN;
+ lodash.isNative = isNative;
+ lodash.isNil = isNil;
+ lodash.isNull = isNull;
+ lodash.isNumber = isNumber;
+ lodash.isObject = isObject;
+ lodash.isObjectLike = isObjectLike;
+ lodash.isPlainObject = isPlainObject;
+ lodash.isRegExp = isRegExp;
+ lodash.isSafeInteger = isSafeInteger;
+ lodash.isSet = isSet;
+ lodash.isString = isString;
+ lodash.isSymbol = isSymbol;
+ lodash.isTypedArray = isTypedArray;
+ lodash.isUndefined = isUndefined;
+ lodash.isWeakMap = isWeakMap;
+ lodash.isWeakSet = isWeakSet;
+ lodash.join = join;
+ lodash.kebabCase = kebabCase;
+ lodash.last = last;
+ lodash.lastIndexOf = lastIndexOf;
+ lodash.lowerCase = lowerCase;
+ lodash.lowerFirst = lowerFirst;
+ lodash.lt = lt;
+ lodash.lte = lte;
+ lodash.max = max;
+ lodash.maxBy = maxBy;
+ lodash.mean = mean;
+ lodash.meanBy = meanBy;
+ lodash.min = min;
+ lodash.minBy = minBy;
+ lodash.stubArray = stubArray;
+ lodash.stubFalse = stubFalse;
+ lodash.stubObject = stubObject;
+ lodash.stubString = stubString;
+ lodash.stubTrue = stubTrue;
+ lodash.multiply = multiply;
+ lodash.nth = nth;
+ lodash.noConflict = noConflict;
+ lodash.noop = noop;
+ lodash.now = now;
+ lodash.pad = pad;
+ lodash.padEnd = padEnd;
+ lodash.padStart = padStart;
+ lodash.parseInt = parseInt;
+ lodash.random = random;
+ lodash.reduce = reduce;
+ lodash.reduceRight = reduceRight;
+ lodash.repeat = repeat;
+ lodash.replace = replace;
+ lodash.result = result;
+ lodash.round = round;
+ lodash.runInContext = runInContext;
+ lodash.sample = sample;
+ lodash.size = size;
+ lodash.snakeCase = snakeCase;
+ lodash.some = some;
+ lodash.sortedIndex = sortedIndex;
+ lodash.sortedIndexBy = sortedIndexBy;
+ lodash.sortedIndexOf = sortedIndexOf;
+ lodash.sortedLastIndex = sortedLastIndex;
+ lodash.sortedLastIndexBy = sortedLastIndexBy;
+ lodash.sortedLastIndexOf = sortedLastIndexOf;
+ lodash.startCase = startCase;
+ lodash.startsWith = startsWith;
+ lodash.subtract = subtract;
+ lodash.sum = sum;
+ lodash.sumBy = sumBy;
+ lodash.template = template;
+ lodash.times = times;
+ lodash.toFinite = toFinite;
+ lodash.toInteger = toInteger;
+ lodash.toLength = toLength;
+ lodash.toLower = toLower;
+ lodash.toNumber = toNumber;
+ lodash.toSafeInteger = toSafeInteger;
+ lodash.toString = toString;
+ lodash.toUpper = toUpper;
+ lodash.trim = trim;
+ lodash.trimEnd = trimEnd;
+ lodash.trimStart = trimStart;
+ lodash.truncate = truncate;
+ lodash.unescape = unescape;
+ lodash.uniqueId = uniqueId;
+ lodash.upperCase = upperCase;
+ lodash.upperFirst = upperFirst;
+
+ // Add aliases.
+ lodash.each = forEach;
+ lodash.eachRight = forEachRight;
+ lodash.first = head;
+
+ mixin(lodash, (function() {
+ var source = {};
+ baseForOwn(lodash, function(func, methodName) {
+ if (!hasOwnProperty.call(lodash.prototype, methodName)) {
+ source[methodName] = func;
+ }
+ });
+ return source;
+ }()), { 'chain': false });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The semantic version number.
+ *
+ * @static
+ * @memberOf _
+ * @type {string}
+ */
+ lodash.VERSION = VERSION;
+
+ // Assign default placeholders.
+ arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
+ lodash[methodName].placeholder = lodash;
+ });
+
+ // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
+ arrayEach(['drop', 'take'], function(methodName, index) {
+ LazyWrapper.prototype[methodName] = function(n) {
+ n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
+
+ var result = (this.__filtered__ && !index)
+ ? new LazyWrapper(this)
+ : this.clone();
+
+ if (result.__filtered__) {
+ result.__takeCount__ = nativeMin(n, result.__takeCount__);
+ } else {
+ result.__views__.push({
+ 'size': nativeMin(n, MAX_ARRAY_LENGTH),
+ 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
+ });
+ }
+ return result;
+ };
+
+ LazyWrapper.prototype[methodName + 'Right'] = function(n) {
+ return this.reverse()[methodName](n).reverse();
+ };
+ });
+
+ // Add `LazyWrapper` methods that accept an `iteratee` value.
+ arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
+ var type = index + 1,
+ isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
+
+ LazyWrapper.prototype[methodName] = function(iteratee) {
+ var result = this.clone();
+ result.__iteratees__.push({
+ 'iteratee': getIteratee(iteratee, 3),
+ 'type': type
+ });
+ result.__filtered__ = result.__filtered__ || isFilter;
+ return result;
+ };
+ });
+
+ // Add `LazyWrapper` methods for `_.head` and `_.last`.
+ arrayEach(['head', 'last'], function(methodName, index) {
+ var takeName = 'take' + (index ? 'Right' : '');
+
+ LazyWrapper.prototype[methodName] = function() {
+ return this[takeName](1).value()[0];
+ };
+ });
+
+ // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
+ arrayEach(['initial', 'tail'], function(methodName, index) {
+ var dropName = 'drop' + (index ? '' : 'Right');
+
+ LazyWrapper.prototype[methodName] = function() {
+ return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
+ };
+ });
+
+ LazyWrapper.prototype.compact = function() {
+ return this.filter(identity);
+ };
+
+ LazyWrapper.prototype.find = function(predicate) {
+ return this.filter(predicate).head();
+ };
+
+ LazyWrapper.prototype.findLast = function(predicate) {
+ return this.reverse().find(predicate);
+ };
+
+ LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
+ if (typeof path == 'function') {
+ return new LazyWrapper(this);
+ }
+ return this.map(function(value) {
+ return baseInvoke(value, path, args);
+ });
+ });
+
+ LazyWrapper.prototype.reject = function(predicate) {
+ return this.filter(negate(getIteratee(predicate)));
+ };
+
+ LazyWrapper.prototype.slice = function(start, end) {
+ start = toInteger(start);
+
+ var result = this;
+ if (result.__filtered__ && (start > 0 || end < 0)) {
+ return new LazyWrapper(result);
+ }
+ if (start < 0) {
+ result = result.takeRight(-start);
+ } else if (start) {
+ result = result.drop(start);
+ }
+ if (end !== undefined) {
+ end = toInteger(end);
+ result = end < 0 ? result.dropRight(-end) : result.take(end - start);
+ }
+ return result;
+ };
+
+ LazyWrapper.prototype.takeRightWhile = function(predicate) {
+ return this.reverse().takeWhile(predicate).reverse();
+ };
+
+ LazyWrapper.prototype.toArray = function() {
+ return this.take(MAX_ARRAY_LENGTH);
+ };
+
+ // Add `LazyWrapper` methods to `lodash.prototype`.
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
+ isTaker = /^(?:head|last)$/.test(methodName),
+ lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
+ retUnwrapped = isTaker || /^find/.test(methodName);
+
+ if (!lodashFunc) {
+ return;
+ }
+ lodash.prototype[methodName] = function() {
+ var value = this.__wrapped__,
+ args = isTaker ? [1] : arguments,
+ isLazy = value instanceof LazyWrapper,
+ iteratee = args[0],
+ useLazy = isLazy || isArray(value);
+
+ var interceptor = function(value) {
+ var result = lodashFunc.apply(lodash, arrayPush([value], args));
+ return (isTaker && chainAll) ? result[0] : result;
+ };
+
+ if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
+ // Avoid lazy use if the iteratee has a "length" value other than `1`.
+ isLazy = useLazy = false;
+ }
+ var chainAll = this.__chain__,
+ isHybrid = !!this.__actions__.length,
+ isUnwrapped = retUnwrapped && !chainAll,
+ onlyLazy = isLazy && !isHybrid;
+
+ if (!retUnwrapped && useLazy) {
+ value = onlyLazy ? value : new LazyWrapper(this);
+ var result = func.apply(value, args);
+ result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
+ return new LodashWrapper(result, chainAll);
+ }
+ if (isUnwrapped && onlyLazy) {
+ return func.apply(this, args);
+ }
+ result = this.thru(interceptor);
+ return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
+ };
+ });
+
+ // Add `Array` methods to `lodash.prototype`.
+ arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
+ var func = arrayProto[methodName],
+ chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
+ retUnwrapped = /^(?:pop|shift)$/.test(methodName);
+
+ lodash.prototype[methodName] = function() {
+ var args = arguments;
+ if (retUnwrapped && !this.__chain__) {
+ var value = this.value();
+ return func.apply(isArray(value) ? value : [], args);
+ }
+ return this[chainName](function(value) {
+ return func.apply(isArray(value) ? value : [], args);
+ });
+ };
+ });
+
+ // Map minified method names to their real names.
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var lodashFunc = lodash[methodName];
+ if (lodashFunc) {
+ var key = (lodashFunc.name + ''),
+ names = realNames[key] || (realNames[key] = []);
+
+ names.push({ 'name': methodName, 'func': lodashFunc });
+ }
+ });
+
+ realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
+ 'name': 'wrapper',
+ 'func': undefined
+ }];
+
+ // Add methods to `LazyWrapper`.
+ LazyWrapper.prototype.clone = lazyClone;
+ LazyWrapper.prototype.reverse = lazyReverse;
+ LazyWrapper.prototype.value = lazyValue;
+
+ // Add chain sequence methods to the `lodash` wrapper.
+ lodash.prototype.at = wrapperAt;
+ lodash.prototype.chain = wrapperChain;
+ lodash.prototype.commit = wrapperCommit;
+ lodash.prototype.next = wrapperNext;
+ lodash.prototype.plant = wrapperPlant;
+ lodash.prototype.reverse = wrapperReverse;
+ lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
+
+ // Add lazy aliases.
+ lodash.prototype.first = lodash.prototype.head;
+
+ if (symIterator) {
+ lodash.prototype[symIterator] = wrapperToIterator;
+ }
+ return lodash;
+ });
+
+ /*--------------------------------------------------------------------------*/
+
+ // Export lodash.
+ var _ = runInContext();
+
+ // Some AMD build optimizers, like r.js, check for condition patterns like:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Expose Lodash on the global object to prevent errors when Lodash is
+ // loaded by a script tag in the presence of an AMD loader.
+ // See http://requirejs.org/docs/errors.html#mismatch for more details.
+ // Use `_.noConflict` to remove Lodash from the global object.
+ root._ = _;
+
+ // Define as an anonymous module so, through path mapping, it can be
+ // referenced as the "underscore" module.
+ define(function() {
+ return _;
+ });
+ }
+ // Check for `exports` after `define` in case a build optimizer adds it.
+ else if (freeModule) {
+ // Export for Node.js.
+ (freeModule.exports = _)._ = _;
+ // Export for CommonJS support.
+ freeExports._ = _;
+ }
+ else {
+ // Export to the global object.
+ root._ = _;
+ }
+}.call(this));
diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js
index b78e0b3e28b..725a237750d 100644
--- a/addons/web/static/src/js/fields/abstract_field.js
+++ b/addons/web/static/src/js/fields/abstract_field.js
@@ -37,6 +37,9 @@ var AbstractField = Widget.extend({
events: {
'keydown': '_onKeydown',
},
+ custom_events: {
+ navigation_move: '_onNavigationMove',
+ },
/**
* If this flag is set to true, the field widget will be reset on every
* change which is made in the view (if the view supports it). This is
@@ -87,7 +90,7 @@ var AbstractField = Widget.extend({
// the 'attrs' property contains the attributes of the xml 'field' tag,
// the inner views...
var fieldsInfo = record.fieldsInfo[this.viewType];
- this.attrs = fieldsInfo && fieldsInfo[name] || {};
+ this.attrs = options.attrs || (fieldsInfo && fieldsInfo[name]) || {};
// this property tracks the current (parsed if needed) value of the field.
// Note that we don't use an event system anymore, using this.get('value')
@@ -165,18 +168,20 @@ var AbstractField = Widget.extend({
* part can be disabled. In that case, note that the focused input/textarea
* will have the cursor at the very end.
*
- * @param {boolean} [noselect=false] if false and the input is of type text
- * or textarea, the content will also be selected
+ * @param {Object} [options]
+ * @param {boolean} [noselect=false] if false and the input
+ * is of type text or textarea, the content will also be selected
+ * @param {Event} [options.event] the event which fired this activation
* @returns {boolean} true if the widget was activated, false if the
* focusable element was not found or invisible
*/
- activate: function (noselect) {
+ activate: function (options) {
var $focusable = this.getFocusableElement();
if ($focusable.length && $focusable.is(':visible')) {
$focusable.focus();
if ($focusable.is('input[type="text"], textarea')) {
$focusable[0].selectionStart = $focusable[0].selectionEnd = $focusable[0].value.length;
- if (!noselect) {
+ if (options && !options.noselect) {
$focusable.select();
}
}
@@ -374,21 +379,60 @@ var AbstractField = Widget.extend({
//--------------------------------------------------------------------------
/**
- * might be controversial: intercept the tab key, to allow the editable list
- * view to control where the focus is.
+ * Intercepts navigation keyboard events to prevent their default behavior
+ * and notifies the view so that it can handle it its own way.
+ *
+ * Note: the navigation keyboard events are stopped so that potential parent
+ * abstract field does not trigger the navigation_move event a second time.
+ * However, this might be controversial, we might wanna let the event
+ * continue its propagation and flag it to say that navigation has already
+ * been handled (TODO ?).
*
* @private
- * @param {KeyEvent} event
+ * @param {KeyEvent} ev
*/
- _onKeydown: function (event) {
- if (event.which === $.ui.keyCode.TAB) {
- // the event needs to be stopped, to prevent other field widgets
- // to retrigger a move event
- event.stopPropagation();
- this.trigger_up(event.shiftKey ? 'move_previous' : 'move_next');
- event.preventDefault();
+ _onKeydown: function (ev) {
+ switch (ev.which) {
+ case $.ui.keyCode.TAB:
+ ev.preventDefault();
+ ev.stopPropagation();
+ this.trigger_up('navigation_move', {
+ direction: ev.shiftKey ? 'previous' : 'next',
+ });
+ break;
+ case $.ui.keyCode.ENTER:
+ ev.stopPropagation();
+ this.trigger_up('navigation_move', {direction: 'next_line'});
+ break;
+ case $.ui.keyCode.UP:
+ ev.stopPropagation();
+ this.trigger_up('navigation_move', {direction: 'up'});
+ break;
+ case $.ui.keyCode.RIGHT:
+ ev.stopPropagation();
+ this.trigger_up('navigation_move', {direction: 'right'});
+ break;
+ case $.ui.keyCode.DOWN:
+ ev.stopPropagation();
+ this.trigger_up('navigation_move', {direction: 'down'});
+ break;
+ case $.ui.keyCode.LEFT:
+ ev.stopPropagation();
+ this.trigger_up('navigation_move', {direction: 'left'});
+ break;
}
},
+ /**
+ * Updates the target data value with the current AbstractField instance.
+ * This allows to consider the parent field in case of nested fields. The
+ * field which triggered the event is still accessible through ev.target.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onNavigationMove: function (ev) {
+ ev.data.target = this;
+ },
});
return AbstractField;
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index b3defa97911..cafa59bbd00 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -56,14 +56,7 @@ var TranslatableFieldMixin = {
* @private
*/
_onTranslate: function () {
- this._rpc({
- route: '/web/dataset/call_button',
- params: {
- model: 'ir.translation',
- method: 'translate_fields',
- args: [this.model, this.res_id, this.name, this.record.getContext()],
- }
- }).then(this.do_action.bind(this));
+ this.trigger_up('translate', {fieldName: this.name, id: this.dataPointID});
},
};
@@ -93,9 +86,6 @@ var DebouncedField = AbstractField.extend({
// _debouncedStarted is used to detect that the user interacted at least
// once with the widget, so that we can prevent it from triggering a
// field_changed in commitChanges if the user didn't change anything
- // (this is required as sometimes it is hard to detect that an unset
- // value is still unset, e.g. if a numerical field contains the value 0,
- // is it because it is still unset or because the user set it to 0?
this._debouncedStarted = false;
if (this.mode === 'edit') {
if (this.DEBOUNCE) {
@@ -229,12 +219,7 @@ var InputField = DebouncedField.extend({
type: 'text',
placeholder: this.attrs.placeholder || "",
});
- // Save cursor position to restore it after updating value
- var selectionStart = this.$input[0].selectionStart;
- var selectionEnd = this.$input[0].selectionEnd;
this.$input.val(this._formatValue(this.value));
- this.$input[0].selectionStart = selectionStart;
- this.$input[0].selectionEnd = selectionEnd;
return this.$input;
},
/**
@@ -282,40 +267,20 @@ var InputField = DebouncedField.extend({
this._doDebouncedAction();
},
/**
- * Implement keyboard movements. Mostly useful for its environment, such
- * as a list view.
+ * Stops the left/right navigation move event if the cursor is not at the
+ * start/end of the input element.
*
- * @override
* @private
- * @param {any} event
+ * @param {OdooEvent} ev
*/
- _onKeydown: function (event) {
+ _onNavigationMove: function (ev) {
+ this._super.apply(this, arguments);
var input = this.$input[0];
- var is_not_selecting;
- switch (event.which) {
- case $.ui.keyCode.DOWN:
- this.trigger_up('move_down');
- break;
- case $.ui.keyCode.UP:
- this.trigger_up('move_up');
- break;
- case $.ui.keyCode.LEFT:
- is_not_selecting = input.selectionEnd === input.selectionStart;
- if (is_not_selecting && input.selectionStart === 0) {
- this.trigger_up('move_left');
- }
- break;
- case $.ui.keyCode.RIGHT:
- is_not_selecting = input.selectionEnd === input.selectionStart;
- if (is_not_selecting && input.selectionEnd === input.value.length) {
- this.trigger_up('move_right');
- }
- break;
- case $.ui.keyCode.ENTER:
- this.trigger_up('move_next_line');
- break;
+ var selecting = (input.selectionEnd !== input.selectionStart);
+ if ((ev.data.direction === "left" && (selecting || input.selectionStart !== 0))
+ || (ev.data.direction === "right" && (selecting || input.selectionStart !== input.value.length))) {
+ ev.stopPropagation();
}
- this._super.apply(this, arguments);
},
});
@@ -380,7 +345,7 @@ var FieldDate = InputField.extend({
* @private
*/
_doDebouncedAction: function () {
- this.datewidget.change_datetime();
+ this.datewidget.changeDatetime();
},
/**
@@ -389,7 +354,7 @@ var FieldDate = InputField.extend({
* @private
*/
_getValue: function () {
- return this.datewidget.get_value();
+ return this.datewidget.getValue();
},
/**
* @override
@@ -418,7 +383,7 @@ var FieldDate = InputField.extend({
* @private
*/
_renderEdit: function () {
- this.datewidget.set_value(this.value);
+ this.datewidget.setValue(this.value);
this.$input = this.datewidget.$input;
},
@@ -447,7 +412,7 @@ var FieldDateTime = FieldDate.extend({
* @private
*/
_getValue: function () {
- var value = this.datewidget.get_value();
+ var value = this.datewidget.getValue();
return value && value.add(-this.getSession().tzOffset, 'minutes');
},
@@ -470,7 +435,7 @@ var FieldDateTime = FieldDate.extend({
*/
_renderEdit: function () {
var value = this.value && this.value.clone().add(this.getSession().tzOffset, 'minutes');
- this.datewidget.set_value(value);
+ this.datewidget.setValue(value);
this.$input = this.datewidget.$input;
},
@@ -610,6 +575,23 @@ var FieldBoolean = AbstractField.extend({
//--------------------------------------------------------------------------
/**
+ * Toggle the checkbox if it is activated due to a click on itself.
+ *
+ * @override
+ */
+ activate: function (options) {
+ var activated = this._super.apply(this, arguments);
+ // The formatValue of boolean fields renders HTML elements similar to
+ // the one rendered by the widget itself. Even though the event might
+ // have been fired on the non-widget version of this field, we can still
+ // test the presence of its o_checkbox class.
+ if (activated && options && options.event && $(options.event.target).parents('.o_checkbox').length) {
+ this._setValue(!this.value); // Toggle the checkbox
+ }
+ return activated;
+ },
+
+ /**
* @override
* @returns {jQuery} the focusable checkbox input
*/
@@ -624,6 +606,20 @@ var FieldBoolean = AbstractField.extend({
isSet: function () {
return true;
},
+ /**
+ * When the checkbox is rerendered, we need to check if it was the actual
+ * origin of the reset. If it is, we need to activate it back so it looks
+ * like it was not rerendered but is still the same input.
+ *
+ * @override
+ */
+ reset: function (record, event) {
+ var rendered = this._super.apply(this, arguments);
+ if (event && event.target.name === this.name) {
+ this.activate();
+ }
+ return rendered;
+ },
//--------------------------------------------------------------------------
// Private
@@ -665,28 +661,16 @@ var FieldBoolean = AbstractField.extend({
*
* @override
* @private
- * @param {KeyEvent} event
+ * @param {KeyEvent} ev
*/
- _onKeydown: function (event) {
- this._super.apply(this, arguments);
- switch (event.which) {
- case $.ui.keyCode.DOWN:
- this.trigger_up('move_down');
- break;
- case $.ui.keyCode.UP:
- this.trigger_up('move_up');
- break;
- case $.ui.keyCode.LEFT:
- this.trigger_up('move_left');
- break;
- case $.ui.keyCode.RIGHT:
- this.trigger_up('move_right');
- break;
+ _onKeydown: function (ev) {
+ switch (ev.which) {
case $.ui.keyCode.ENTER:
this.$input.prop('checked', !this.value);
this._setValue(!this.value);
- break;
+ return;
}
+ this._super.apply(this, arguments);
},
});
@@ -1774,7 +1758,8 @@ var JournalDashboardGraph = AbstractField.extend({
this.data = JSON.parse(this.value);
},
start: function () {
- nv.utils.windowResize(this._onResize.bind(this));
+ this._onResize = this._onResize.bind(this);
+ nv.utils.windowResize(this._onResize);
return this._super.apply(this, arguments);
},
destroy: function () {
@@ -1909,10 +1894,10 @@ var FieldDomain = AbstractField.extend({
"click .o_domain_show_selection_button": "_onShowSelectionButtonClick",
"click .o_field_domain_dialog_button": "_onDialogEditButtonClick",
}),
- custom_events: {
+ custom_events: _.extend({}, AbstractField.prototype.custom_events, {
"domain_changed": "_onDomainSelectorValueChange",
"domain_selected": "_onDomainSelectorDialogValueChange",
- },
+ }),
/**
* @constructor
* @override init from AbstractField
diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js
index 9a683954e7e..ed3014d9bb6 100644
--- a/addons/web/static/src/js/fields/field_utils.js
+++ b/addons/web/static/src/js/fields/field_utils.js
@@ -71,7 +71,7 @@ function formatChar(value) {
* @returns {string}
*/
function formatDate(value, field, options) {
- if (!value) {
+ if (value === false) {
return "";
}
if (!options || !('timezone' in options) || options.timezone) {
@@ -96,7 +96,7 @@ function formatDate(value, field, options) {
* @returns {string}
*/
function formatDateTime(value, field, options) {
- if (!value) {
+ if (value === false) {
return "";
}
if (!options || !('timezone' in options) || options.timezone) {
@@ -113,7 +113,7 @@ function formatDateTime(value, field, options) {
* Returns a string representing a float. The result takes into account the
* user settings (to display the correct decimal separator).
*
- * @param {float} value the value that should be formatted
+ * @param {float|false} value the value that should be formatted
* @param {Object} [field] a description of the field (returned by fields_get
* for example). It may contain a description of the number of digits that
* should be used.
@@ -124,6 +124,9 @@ function formatDateTime(value, field, options) {
* @returns {string}
*/
function formatFloat(value, field, options) {
+ if (value === false) {
+ return "";
+ }
var l10n = core._t.database.parameters;
var precision;
if (options && options.digits) {
@@ -213,7 +216,7 @@ function formatX2Many(value) {
* Returns a string representing a monetary value. The result takes into account
* the user settings (to display the correct decimal separator, currency, ...).
*
- * @param {float} value the value that should be formatted
+ * @param {float|false} value the value that should be formatted
* @param {Object} [field]
* a description of the field (returned by fields_get for example). It
* may contain a description of the number of digits that should be used.
@@ -238,6 +241,9 @@ function formatX2Many(value) {
* @returns {string}
*/
function formatMonetary(value, field, options) {
+ if (value === false) {
+ return "";
+ }
options = options || {};
var currency = options.currency;
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index e9fa7dd09d1..10d72a1398d 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -14,6 +14,7 @@ odoo.define('web.relational_fields', function (require) {
*/
var AbstractField = require('web.AbstractField');
+var basicFields = require('web.basic_fields');
var concurrency = require('web.concurrency');
var ControlPanel = require('web.ControlPanel');
var dialogs = require('web.view_dialogs');
@@ -76,10 +77,10 @@ var M2ODialog = Dialog.extend({
var FieldMany2One = AbstractField.extend({
supportedFieldTypes: ['many2one'],
template: 'FieldMany2One',
- custom_events: {
+ custom_events: _.extend({}, AbstractField.prototype.custom_events, {
'quick_create': '_onQuickCreate',
'search_create_popup': '_onSearchCreatePopup',
- },
+ }),
events: _.extend({}, AbstractField.prototype.events, {
'click input': '_onInputClick',
'focusout input': '_onInputFocusout',
@@ -461,6 +462,19 @@ var FieldMany2One = AbstractField.extend({
}
},
/**
+ * Stops the left/right navigation move event if the cursor is not at the
+ * start/end of the input element. Stops any navigation move event if the
+ * user is selecting text.
+ *
+ * TODO this is a duplicate of InputField._onNavigationMove, maybe this
+ * should be done in a mixin or, better, the m2o field should be an
+ * InputField (but this requires some refactoring).
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onNavigationMove: basicFields.InputField.prototype._onNavigationMove,
+ /**
* @private
* @param {OdooEvent} event
*/
@@ -600,7 +614,7 @@ var FieldX2Many = AbstractField.extend({
if (command.operation === 'UPDATE') {
var state = record.data[this.name];
var fieldNames = state.getFieldNames();
- this.renderer.confirmChange(state, command.id, fieldNames);
+ this.renderer.confirmChange(state, command.id, fieldNames, ev.initialEvent);
return $.when();
}
}
@@ -624,7 +638,7 @@ var FieldX2Many = AbstractField.extend({
return this._super();
}
if (this.renderer) {
- this.renderer.updateState(this.value);
+ this.renderer.updateState(this.value, {});
this.pager.updateState({ size: this.value.count });
return $.when();
}
@@ -732,8 +746,8 @@ var FieldX2Many = AbstractField.extend({
onFailure: def.reject.bind(def),
});
} else {
- self.renderer.setRowMode(recordID, 'readonly');
- def.resolve();
+ self.renderer.setRowMode(recordID, 'readonly')
+ .done(def.resolve.bind(def));
}
});
return def;
@@ -777,7 +791,8 @@ var FieldX2Many = AbstractField.extend({
*/
_onEditLine: function (ev) {
ev.stopPropagation();
- this.renderer.setRowMode(ev.data.recordID, 'edit');
+ this.renderer.setRowMode(ev.data.recordID, 'edit')
+ .done(ev.data.onSuccess);
},
/**
* Updates the given record with the changes.
@@ -787,12 +802,19 @@ var FieldX2Many = AbstractField.extend({
*/
_onFieldChanged: function (ev) {
if (ev.target === this) {
+ ev.initialEvent = this.lastInitialEvent;
return;
}
ev.stopPropagation();
// changes occured in an editable list
var changes = ev.data.changes;
+ // save the initial event triggering the field_changed, as it will be
+ // necessary when the field triggering this event will be reset (to
+ // prevent it from re-rendering itself, formatting its value, loosing
+ // the focus... while still being edited)
+ this.lastInitialEvent = undefined;
if (Object.keys(changes).length) {
+ this.lastInitialEvent = ev;
this._setValue({
operation: 'UPDATE',
id: ev.data.dataPointID,
@@ -1050,6 +1072,11 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({
this._generatedMetadata();
},
+ destroy: function () {
+ this._super();
+ $(window).off(this.fileupload_id);
+ },
+
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
@@ -1208,13 +1235,11 @@ var FieldMany2ManyTags = AbstractField.extend({
tag_template: "FieldMany2ManyTag",
className: "o_field_many2manytags",
supportedFieldTypes: ['many2many'],
- custom_events: {
+ custom_events: _.extend({}, AbstractField.prototype.custom_events, {
field_changed: '_onFieldChanged',
- move_next: '_onMoveNext',
- },
+ }),
events: _.extend({}, AbstractField.prototype.events, {
'click .o_delete': '_onDeleteTag',
- 'keydown .o_field_many2one input': '_onKeyDown',
}),
fieldsToFetch: {
color: {type: 'integer'},
@@ -1358,42 +1383,35 @@ var FieldMany2ManyTags = AbstractField.extend({
this._removeTag($(event.target).parent().data('id'));
},
/**
+ * Controls the changes made in the internal m2o field.
+ *
* @private
- * @param {OdooEvent} event
+ * @param {OdooEvent} ev
*/
- _onFieldChanged: function (event) {
- if (event.target === this) {
+ _onFieldChanged: function (ev) {
+ if (ev.target !== this.many2one) {
return;
}
- event.stopPropagation();
- var new_value = event.data.changes[this.name];
- if (new_value) {
- this._addTag(new_value);
+ ev.stopPropagation();
+ var newValue = ev.data.changes[this.name];
+ if (newValue) {
+ this._addTag(newValue);
this.many2one.reinitialize(false);
}
},
/**
* @private
- * @param {KeyboardEvent} event
+ * @param {KeyboardEvent} ev
*/
- _onKeyDown: function (event) {
- if ($(event.target).val() === "" && event.which === $.ui.keyCode.BACKSPACE) {
+ _onKeydown: function (ev) {
+ if (ev.which === $.ui.keyCode.BACKSPACE && this.$('input').val() === "") {
var $badges = this.$('.badge');
if ($badges.length) {
this._removeTag($badges.last().data('id'));
+ return;
}
}
- },
- /**
- * @private
- * @param {OdooEvent} event
- */
- _onMoveNext: function (event) {
- if (event.target === this) {
- return;
- }
- // Intercept event triggered up by the many2one, to prevent triggering it twice
- event.stopPropagation();
+ this._super.apply(this, arguments);
},
/**
* @private
diff --git a/addons/web/static/src/js/services/data_manager.js b/addons/web/static/src/js/services/data_manager.js
index cf49dd3aaec..5131db19028 100644
--- a/addons/web/static/src/js/services/data_manager.js
+++ b/addons/web/static/src/js/services/data_manager.js
@@ -312,7 +312,7 @@ return core.Class.extend({
var defaultOrder = innerFieldsView.arch.attrs.default_order;
if (defaultOrder) {
attrs.orderedBy = _.map(defaultOrder.split(','), function (order) {
- order = order.split(' ');
+ order = order.trim().split(' ');
return {name: order[0], asc: order[1] !== 'desc'};
});
}
diff --git a/addons/web/static/src/js/views/abstract_renderer.js b/addons/web/static/src/js/views/abstract_renderer.js
index 70ad5350670..7d10f05eab8 100644
--- a/addons/web/static/src/js/views/abstract_renderer.js
+++ b/addons/web/static/src/js/views/abstract_renderer.js
@@ -65,15 +65,18 @@ return Widget.extend({
setLocalState: function (localState) {
},
/**
- * update the state of the view. It always retrigger a full rerender.
+ * Updates the state of the view. It retriggers a full rerender, unless told
+ * otherwise (for optimization for example).
*
* @param {any} state
* @param {Object} params
+ * @param {boolean} [params.noRender=false]
+ * if true, the method only updates the state without rerendering
* @returns {Deferred}
*/
updateState: function (state, params) {
this.state = state;
- return this._render();
+ return params.noRender ? $.when() : this._render();
},
//--------------------------------------------------------------------------
diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js
index af3e36ad45b..1f91fc7a796 100644
--- a/addons/web/static/src/js/views/abstract_view.js
+++ b/addons/web/static/src/js/views/abstract_view.js
@@ -109,7 +109,7 @@ var AbstractView = Class.extend({
var defaultOrder = viewInfo.arch.attrs.default_order;
if (defaultOrder) {
this.loadParams.orderedBy = _.map(defaultOrder.split(','), function (order) {
- order = order.split(' ');
+ order = order.trim().split(' ');
return {name: order[0], asc: order[1] !== 'desc'};
});
}
diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js
index b7cd40d9e7c..1e0187b348e 100644
--- a/addons/web/static/src/js/views/basic/basic_controller.js
+++ b/addons/web/static/src/js/views/basic/basic_controller.js
@@ -19,7 +19,8 @@ var _t = core._t;
var BasicController = AbstractController.extend(FieldManagerMixin, {
custom_events: _.extend({}, AbstractController.prototype.custom_events, FieldManagerMixin.custom_events, {
reload: '_onReload',
- sidebar_data_asked: '_onSidebarDataAsked'
+ sidebar_data_asked: '_onSidebarDataAsked',
+ translate: '_onTranslate',
}),
/**
* @override
@@ -118,13 +119,18 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
var self = this;
recordID = recordID || this.handle;
return this.canBeDiscarded(recordID).then(function (needDiscard) {
+ if (options && options.readonlyIfRealDiscard && !needDiscard) {
+ return;
+ }
+
if (needDiscard) { // Just some optimization
self.model.discardChanges(recordID);
}
- if (options && options.readonlyIfRealDiscard && !needDiscard) {
+ if (self.model.isNew(recordID)) {
+ self._abandonRecord(recordID);
return;
}
- self._setMode('readonly', recordID);
+ return self._confirmSave(recordID);
});
},
/**
@@ -164,6 +170,8 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
* @param {string} [recordID] - default to main recordID
* @param {Object} [options]
* @returns {Deferred}
+ * Resolved with the list of field names (whose value has been modified)
+ * Rejected if the record can't be saved
*/
saveRecord: function (recordID, options) {
// Some field widgets can't detect (all) their changes immediately or
@@ -286,7 +294,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
var self = this;
function doIt() {
return self.model
- .deleteRecords(ids, self.modelName, self.handle)
+ .deleteRecords(ids, self.modelName)
.then(self._onDeletedRecords.bind(self, ids));
}
if (this.confirmOnDelete) {
@@ -362,6 +370,8 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
* if true, the record will only be 'locally' saved: its changes
* will move from the _changes key to the data key
* @returns {Deferred}
+ * Resolved with the list of field names (whose value has been modified)
+ * Rejected if the record can't be saved
*/
_saveRecord: function (recordID, options) {
recordID = recordID || this.handle;
@@ -371,22 +381,24 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
savePoint: false,
});
- var def = $.Deferred();
// Check if the view is in a valid state for saving
// Note: it is the model's job to do nothing if there is nothing to save
if (this.canBeSaved(recordID)) {
- def = this.model.save(recordID, { // Save then leave edit mode
+ var self = this;
+ var def = this.model.save(recordID, { // Save then leave edit mode
reload: options.reload,
savePoint: options.savePoint,
});
- } else {
- def.reject(); // Cannot be saved, do nothing at all
- }
-
- if (options.stayInEdit) {
+ if (!options.stayInEdit) {
+ def = def.then(function (fieldNames) {
+ return self._confirmSave(recordID).then(function () {
+ return fieldNames;
+ });
+ });
+ }
return def;
} else {
- return def.then(this._setMode.bind(this, 'readonly', recordID));
+ return $.Deferred().reject(); // Cannot be saved
}
},
/**
@@ -397,17 +409,13 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
* @private
* @param {string} mode - 'readonly' or 'edit'
* @param {string} [recordID]
+ * @returns {Deferred}
*/
_setMode: function (mode, recordID) {
- recordID = recordID || this.handle;
- // If trying to make a temporary record readonly, discard the record
- if (mode === 'readonly' && this.model.isNew(recordID)) {
- this._abandonRecord(recordID);
- return;
- }
- if (recordID === this.handle) {
- this.update({mode: mode}, {reload: false});
+ if ((recordID || this.handle) === this.handle) {
+ return this.update({mode: mode}, {reload: false});
}
+ return $.when();
},
/**
* Helper method, to get the current environment variables from the model
@@ -497,6 +505,23 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
var sidebarEnv = this._getSidebarEnv();
event.data.callback(sidebarEnv);
},
+ /**
+ * open the translation view for the current field
+ *
+ * @private
+ * @param {OdooEvent} event
+ */
+ _onTranslate: function (event) {
+ var record = this.model.get(event.data.id, {raw: true});
+ this._rpc({
+ route: '/web/dataset/call_button',
+ params: {
+ model: 'ir.translation',
+ method: 'translate_fields',
+ args: [record.model, record.res_id, event.data.fieldName, record.getContext()],
+ }
+ }).then(this.do_action.bind(this));
+ },
});
return BasicController;
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js
index 17cb4d277c2..5e5b36472f5 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -180,15 +180,16 @@ var BasicModel = AbstractModel.extend({
});
},
/**
- * Delete a list of records, then, if a parentID is given, reload the
- * parent.
+ * Delete a list of records, then, if the records have a parent, reload it.
*
* @todo we should remove the deleted records from the localData
- * @todo why can't we infer modelName?
+ * @todo why can't we infer modelName? Because of grouped datapoint
+ * --> res_id doesn't correspond to the model and we don't have the
+ * information about the related model
*
* @param {string[]} recordIds list of local resources ids. They should all
- * be of type 'record', and of the same model
- * @param {string} modelName
+ * be of type 'record', be of the same model and have the same parent.
+ * @param {string} modelName mode name used to unlink the records
* @returns {Deferred}
*/
deleteRecords: function (recordIds, modelName) {
@@ -202,9 +203,15 @@ var BasicModel = AbstractModel.extend({
})
.then(function () {
_.each(records, function (record) {
- record.res_ids.splice(record.offset, 1);
- record.res_id = record.res_ids[record.offset];
- record.count--;
+ var parent = record.parentID && self.localData[record.parentID];
+ if (parent && parent.type === 'list') {
+ parent.data = _.without(parent.data, record.id);
+ delete self.localData[record.id];
+ } else {
+ record.res_ids.splice(record.offset, 1);
+ record.res_id = record.res_ids[record.offset];
+ record.count--;
+ }
});
});
},
@@ -289,35 +296,27 @@ var BasicModel = AbstractModel.extend({
return null;
}
- var record = this.localData[id];
+ var element = this.localData[id];
if (options.env) {
var env = {
- ids: record.res_ids ? record.res_ids.slice(0) : [],
+ ids: element.res_ids ? element.res_ids.slice(0) : [],
};
- if (record.type === 'record') {
- env.currentId = this.isNew(record.id) ? undefined : record.res_id;
+ if (element.type === 'record') {
+ env.currentId = this.isNew(element.id) ? undefined : element.res_id;
}
return env;
}
- // do not copy fields: this has a really big performance cost, for views
- // with many records and lots of fields (for ex, kanban view contacts)
- var fields = record.fields;
- delete record.fields;
- var element = $.extend(true, {}, record);
- record.fields = fields;
- element.fields = fields;
- var field, relDataPoint;
if (element.type === 'record') {
- // apply changes
- _.extend(element.data, element._changes);
- for (var fieldName in element.data) {
- field = element.fields[fieldName];
- if (element.data[fieldName] === null) {
- element.data[fieldName] = false;
+ var data = _.extend({}, element.data, element._changes);
+ var relDataPoint;
+ for (var fieldName in data) {
+ var field = element.fields[fieldName];
+ if (data[fieldName] === null) {
+ data[fieldName] = false;
}
if (!field) {
continue;
@@ -326,72 +325,110 @@ var BasicModel = AbstractModel.extend({
if (field.type === 'float' ||
field.type === 'integer' ||
field.type === 'monetary') {
- element.data[fieldName] = element.data[fieldName] || 0;
+ data[fieldName] = data[fieldName] || 0;
}
}
// get relational datapoint
if (field.type === 'many2one') {
if (options.raw) {
- relDataPoint = this.localData[element.data[fieldName]];
- element.data[fieldName] = relDataPoint ? relDataPoint.res_id : false;
+ relDataPoint = this.localData[data[fieldName]];
+ data[fieldName] = relDataPoint ? relDataPoint.res_id : false;
} else {
- element.data[fieldName] = this.get(element.data[fieldName]) || false;
+ data[fieldName] = this.get(data[fieldName]) || false;
}
}
if (field.type === 'one2many' || field.type === 'many2many') {
if (options.raw) {
- relDataPoint = this.localData[element.data[fieldName]];
- var ids = _.map(relDataPoint.data, function (id) {
+ relDataPoint = this.localData[data[fieldName]];
+ var relData = relDataPoint._changes || relDataPoint.data;
+ var ids = _.map(relData, function (id) {
return self.localData[id].res_id;
});
- element.data[fieldName] = ids;
+ data[fieldName] = ids;
} else {
- element.data[fieldName] = this.get(element.data[fieldName]) || [];
+ data[fieldName] = this.get(data[fieldName]) || [];
}
}
}
+ var record = {
+ context: _.extend({}, element.context),
+ count: element.count,
+ data: data,
+ domain: element.domain.slice(0),
+ fields: element.fields,
+ fieldsInfo: element.fieldsInfo,
+ getContext: element.getContext,
+ getDomain: element.getDomain,
+ getEvalContext: element.getEvalContext,
+ getFieldNames: element.getFieldNames,
+ id: element.id,
+ limit: element.limit,
+ model: element.model,
+ offset: element.offset,
+ res_ids: element.res_ids.slice(0),
+ specialData: _.extend({}, element.specialData),
+ type: 'record',
+ viewType: element.viewType,
+ };
- // this is not strictly necessary, but it hides some implementation
- // details, and can easily be removed if needed.
- delete element.orderedBy;
- delete element.aggregateValues;
- delete element.groupedBy;
- if (this.isNew(element.id)) {
- delete element.res_id;
+ if (!this.isNew(element.id)) {
+ record.res_id = element.res_id;
}
var evalContext;
- Object.defineProperty(element, 'evalContext', {
+ Object.defineProperty(record, 'evalContext', {
get: function () {
- evalContext = evalContext || self._getEvalContext(record);
+ evalContext = evalContext || self._getEvalContext(element);
return evalContext;
},
});
+ return record;
}
- if (element.type === 'list') {
- // apply changes if any
- if (element._changes) {
- element.data = element._changes;
- element.count = element._changes.length;
- element.res_ids = _.map(element._changes, function (elemID) {
- return self.localData[elemID].res_id;
- });
- }
- // get relational datapoint
- element.data = _.map(element.data, function (elemID) {
- return self.get(elemID);
+
+ // here, type === 'list'
+ var listData, listCount, resIDs;
+ if (element._changes) {
+ listData = element._changes;
+ listCount = listData.length;
+ resIDs = _.map(listData, function (elemID) {
+ return self.localData[elemID].res_id;
});
+ } else {
+ listData = element.data;
+ listCount = element.count;
+ resIDs = element.res_ids;
}
-
- delete element._cache;
- delete element._changes;
- delete element._forceM2MLink;
- delete element.static;
- delete element.parentID;
- delete element.relation_field;
- delete element.rawContext;
-
- return element;
+ listData = _.map(listData, function (elemID) {
+ return self.get(elemID, options);
+ });
+ var list = {
+ aggregateValues: _.extend({}, element.aggregateValues),
+ context: _.extend({}, element.context),
+ count: listCount,
+ data: listData,
+ domain: element.domain.slice(0),
+ fields: element.fields,
+ getContext: element.getContext,
+ getDomain: element.getDomain,
+ getEvalContext: element.getEvalContext,
+ getFieldNames: element.getFieldNames,
+ groupedBy: element.groupedBy,
+ id: element.id,
+ isOpen: element.isOpen,
+ limit: element.limit,
+ model: element.model,
+ offset: element.offset,
+ orderedBy: element.orderedBy,
+ res_id: element.res_id,
+ res_ids: resIDs,
+ type: 'list',
+ value: element.value,
+ viewType: element.viewType,
+ };
+ if (element.fieldsInfo) {
+ list.fieldsInfo = element.fieldsInfo;
+ }
+ return list;
},
/**
* Returns true if a record is dirty. A record is considered dirty if it has
@@ -678,6 +715,7 @@ var BasicModel = AbstractModel.extend({
* be 'locally' saved: its changes written in a _savePoint key that can
* be restored later by call discardChanges with option rollback to true
* @returns {Deferred}
+ * Resolved with the list of field names (whose value has been modified)
*/
save: function (record_id, options) {
var self = this;
@@ -693,7 +731,6 @@ var BasicModel = AbstractModel.extend({
rec._savePoint = _.extend({}, newValue);
}
});
- return $.when();
}
var shouldReload = 'reload' in options ? options.reload : true;
var method = self.isNew(record_id) ? 'create' : 'write';
@@ -712,10 +749,17 @@ var BasicModel = AbstractModel.extend({
});
}
+ var def = $.Deferred();
+ var changedFields = Object.keys(changes);
+
+ if (options.savePoint) {
+ return def.resolve(changedFields);
+ }
+
// in the case of a write, only perform the RPC if there are changes to save
- if (method === 'create' || Object.keys(changes).length) {
+ if (method === 'create' || changedFields.length) {
var args = method === 'write' ? [[record.data.id], changes] : [changes];
- return self._rpc({
+ self._rpc({
model: record.model,
method: method,
args: args,
@@ -729,23 +773,26 @@ var BasicModel = AbstractModel.extend({
record.count++;
}
- // Update the data directly or reload them
- var def;
- if (shouldReload) {
- def = self._fetchRecord(record);
- } else {
- _.extend(record.data, record._changes);
- }
+ var _changes = record._changes;
// Erase changes as they have been applied
record._changes = {};
record._isDirty = false;
- return def;
+ // Update the data directly or reload them
+ if (shouldReload) {
+ self._fetchRecord(record).then(function (record) {
+ def.resolve(changedFields);
+ });
+ } else {
+ _.extend(record.data, _changes);
+ def.resolve(changedFields);
+ }
});
} else {
- return $.when(record_id);
+ def.resolve(changedFields);
}
+ return def;
});
},
/**
@@ -2038,7 +2085,7 @@ var BasicModel = AbstractModel.extend({
return true;
case 'one2many':
case 'many2many':
- return value.count > 0;
+ return value.length > 0;
default:
return value !== false;
}
@@ -2267,13 +2314,13 @@ var BasicModel = AbstractModel.extend({
});
x2manyList._changes = x2manyList._changes || [];
x2manyList._changes.push(r.id);
- r._changes = value[2];
// this is necessary so the fields are initialized
- for (var fieldName in value[2]) {
+ _.each(r.getFieldNames(), function (fieldName) {
r.data[fieldName] = null;
- }
+ });
+ r._changes = _.defaults(value[2], r.data);
for (var name in r._changes) {
var isFieldInView = name in r.fields;
if (isFieldInView && r.fields[name].type === 'many2one') {
diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js
index 65f444ad7b3..907ea7ddc07 100644
--- a/addons/web/static/src/js/views/basic/basic_renderer.js
+++ b/addons/web/static/src/js/views/basic/basic_renderer.js
@@ -16,12 +16,7 @@ var qweb = core.qweb;
var BasicRenderer = AbstractRenderer.extend({
custom_events: {
- /**
- * All basic renderers should be able to handle widget navigation
- * through the TAB key.
- */
- move_next: '_onMoveNext',
- move_previous: '_onMovePrevious',
+ navigation_move: '_onNavigationMove',
},
/**
* Basic renderers implements the concept of "mode", they can either be in
@@ -169,7 +164,7 @@ var BasicRenderer = AbstractRenderer.extend({
var recordWidgets = this.allFieldWidgets[record.id] || [];
for (var i = 0 ; i < recordWidgets.length ; i++) {
- var activated = recordWidgets[currentIndex].activate();
+ var activated = recordWidgets[currentIndex].activate({event: options.event});
if (activated) {
return currentIndex;
}
@@ -600,24 +595,15 @@ var BasicRenderer = AbstractRenderer.extend({
//--------------------------------------------------------------------------
/**
- * When someone presses TAB in a widget, it is nice to be able to go to the
- * next widget, especially since the TAB key event is preventDefaulted
+ * When someone presses the TAB/UP/DOWN/... key in a widget, it is nice to
+ * be able to navigate in the view (default browser behaviors are disabled
+ * by Odoo).
*
* @abstract
* @private
* @param {OdooEvent} ev
*/
- _onMoveNext: function (ev) {},
- /**
- * When someone presses SHIFT+TAB in a widget, it is nice to be able to go
- * back to the previous widget, especially since the TAB key event is
- * preventDefaulted
- *
- * @abstract
- * @private
- * @param {OdooEvent} ev
- */
- _onMovePrevious: function (ev) {},
+ _onNavigationMove: function (ev) {},
});
return BasicRenderer;
diff --git a/addons/web/static/src/js/views/calendar/calendar_quick_create.js b/addons/web/static/src/js/views/calendar/calendar_quick_create.js
index 2e6fcae5cf5..c63ad5a47f2 100644
--- a/addons/web/static/src/js/views/calendar/calendar_quick_create.js
+++ b/addons/web/static/src/js/views/calendar/calendar_quick_create.js
@@ -17,6 +17,10 @@ var QWeb = core.qweb;
* @type {*}
*/
var QuickCreate = Dialog.extend({
+ events: _.extend({}, Dialog.events, {
+ 'keyup input': '_onkeyup',
+ }),
+
/**
* @constructor
* @param {Widget} parent
@@ -32,7 +36,6 @@ var QuickCreate = Dialog.extend({
// Can hold data pre-set from where you clicked on agenda
this.dataTemplate = dataTemplate || {};
this.dataCalendar = dataCalendar;
- this.$input = $();
var self = this;
this._super(parent, {
@@ -46,7 +49,7 @@ var QuickCreate = Dialog.extend({
}},
{text: _t("Edit"), click: function () {
dataCalendar.disableQuickCreate = true;
- dataCalendar.title = self.$input.val().trim();
+ dataCalendar.title = self.$('input').val().trim();
dataCalendar.on_save = self.destroy.bind(self);
self.trigger_up('openCreate', dataCalendar);
}},
@@ -55,37 +58,13 @@ var QuickCreate = Dialog.extend({
$content: QWeb.render('CalendarView.quick_create', {widged: this})
});
},
- /**
- * @override
- * @returns {Deferred}
- */
- start: function () {
- var self = this;
-
- if (this.options.disableQuickCreate) {
- this.slow_create();
- return;
- }
- this.$input = this.$('input').keyup(function enterHandler (e) {
- if(e.keyCode === $.ui.keyCode.ENTER) {
- self.$input.off('keyup', enterHandler);
- if (!self._quickAdd(self.dataCalendar)){
- self.$input.on('keyup', enterHandler);
- }
- } else if (e.keyCode === $.ui.keyCode.ESCAPE && self._buttons) {
- self.close();
- }
- });
-
- return this._super();
- },
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
focus: function () {
- this.$input.focus();
+ this.$('input').focus();
},
//--------------------------------------------------------------------------
@@ -110,10 +89,27 @@ var QuickCreate = Dialog.extend({
*/
_quickAdd: function (dataCalendar) {
dataCalendar = $.extend({}, this.dataTemplate, dataCalendar);
- var val = this.$input.val().trim();
+ var val = this.$('input').val().trim();
dataCalendar.title = val;
return (val)? this.trigger_up('quickCreate', {data: dataCalendar, options: this.options}) : false;
},
+ /**
+ * @private
+ * @param {keyEvent} event
+ */
+ _onkeyup: function (event) {
+ if (this._flagEnter) {
+ return;
+ }
+ if(event.keyCode === $.ui.keyCode.ENTER) {
+ this._flagEnter = true;
+ if (!this._quickAdd(this.dataCalendar)){
+ this._flagEnter = false;
+ }
+ } else if (event.keyCode === $.ui.keyCode.ESCAPE && this._buttons) {
+ this.close();
+ }
+ },
});
return QuickCreate;
diff --git a/addons/web/static/src/js/views/form/form_controller.js b/addons/web/static/src/js/views/form/form_controller.js
index f15bdfa5382..99d21552be6 100644
--- a/addons/web/static/src/js/views/form/form_controller.js
+++ b/addons/web/static/src/js/views/form/form_controller.js
@@ -67,7 +67,7 @@ var FormController = BasicController.extend({
}).then(function (handle) {
self.handle = handle;
self._updateEnv();
- self._setMode('edit');
+ return self._setMode('edit');
});
},
/**
@@ -168,6 +168,35 @@ var FormController = BasicController.extend({
this._updateSidebar();
}
},
+ /**
+ * Show a warning message if the user modified a translated field. For each
+ * field, the notification provides a link to edit the field's translations.
+ *
+ * @override
+ */
+ saveRecord: function () {
+ var result = this._super.apply(this, arguments);
+ if (_t.database.multi_lang) {
+ var self = this;
+ result.then(function (changedFields) {
+ if (!changedFields.length) {
+ return changedFields;
+ }
+ var fields = self.renderer.state.fields;
+ var alertFields = [];
+ for (var k = 0; k < changedFields.length; k++) {
+ var field = fields[changedFields[k]];
+ if (field.translate) {
+ alertFields.push(field);
+ }
+ }
+ if (alertFields.length) {
+ self.renderer.displayTranslationAlert(alertFields);
+ }
+ });
+ }
+ return result;
+ },
//--------------------------------------------------------------------------
// Private
@@ -180,10 +209,15 @@ var FormController = BasicController.extend({
* @private
* @override method from field manager mixin
* @param {string} id
+ * @returns {Deferred}
*/
_confirmSave: function (id) {
if (id === this.handle) {
- return this.reload();
+ if (this.mode === 'readonly') {
+ return this.reload();
+ } else {
+ return this._setMode('readonly');
+ }
} else {
// a subrecord changed, so update the corresponding relational field
// i.e. the one whose value is a record with the given id or a list
@@ -243,6 +277,12 @@ var FormController = BasicController.extend({
*/
_updateButtons: function () {
if (this.$buttons) {
+ if (this.footerToButtons) {
+ var $footer = this.$('footer');
+ if ($footer.length) {
+ this.$buttons.empty().append($footer);
+ }
+ }
var edit_mode = (this.mode === 'edit');
this.$buttons.find('.o_form_buttons_edit')
.toggleClass('o_hidden', !edit_mode);
@@ -416,7 +456,7 @@ var FormController = BasicController.extend({
res_id: record && record.res_id,
res_model: data.field.relation,
shouldSaveLocally: true,
- title: (record ? _t("Open:") : _t("Create")) + data.field.string,
+ title: (record ? _t("Open: ") : _t("Create ")) + (event.target.string || data.field.string),
}).open();
},
/**
diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js
index f6bcbd49eeb..a2c0d2129ab 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -10,6 +10,9 @@ var qweb = core.qweb;
var FormRenderer = BasicRenderer.extend({
className: "o_form_view",
+ events: _.extend({}, BasicRenderer.prototype.events, {
+ 'click .o_notification_box .oe_field_translate': '_onTranslate',
+ }),
/**
* @override
*/
@@ -49,6 +52,25 @@ var FormRenderer = BasicRenderer.extend({
return fieldNames;
},
/**
+ * Show a warning message if the user modified a translated field. For each
+ * field, the notification provides a link to edit the field's translations.
+ *
+ * @param {Object[]} alertFields: field list
+ */
+ displayTranslationAlert: function (alertFields) {
+ this.$('.o_notification_box').remove();
+ var $notification = $(qweb.render('notification-box', {type: 'info'}))
+ .append(qweb.render('translation-alert', {
+ fields: alertFields,
+ lang: _t.database.parameters.name
+ }));
+ if (this.$('.o_form_statusbar').length) {
+ this.$('.o_form_statusbar').after($notification);
+ } else {
+ this.$el.prepend($notification);
+ }
+ },
+ /**
* @see BasicRenderer.confirmChange
*
* We need to reapply the idForLabel postprocessing since some widgets may
@@ -302,106 +324,98 @@ var FormRenderer = BasicRenderer.extend({
* @param {Object} node
* @returns {jQueryElement}
*/
- _renderInnerField: function (node) {
- var self = this;
- var fieldName = node.attrs.name;
- var field = this.state.fields[fieldName];
- var fieldDescr = node.attrs.string || field.string;
- var widget = this._renderFieldWidget(node, this.state);
-
- if (!node.attrs.nolabel) {
- var $label = $('<label>', {
- class: 'o_form_label',
- for: this._getIDForLabel(node.attrs.name),
- text: fieldDescr,
- });
- this._registerModifiers(node, this.state, $label, {
- callback: function (element, modifiers, record) {
- element.$el.toggleClass('o_form_label_empty', !!( // FIXME condition is evaluated twice (label AND widget...)
- record.data.id
- && (modifiers.readonly || self.mode === 'readonly')
- && !widget.isSet() // getting like this because it could have been re-rendered...
- ));
- },
- });
- return $('<tr>')
- .append($('<td class="o_td_label">').append($label))
- .append($('<td style="width: 100%">').append(widget.$el));
- } else {
- var style = {
- width: 100/2 + '%',
- };
- return $('<tr>')
- .append($('<td colspan="1">').css(style).append(widget.$el));
- }
- },
- /**
- * @private
- * @param {Object} node
- * @returns {jQueryElement}
- */
_renderInnerGroup: function (node) {
- var $result = $('<table class="o_group o_inner_group"/>');
+ var self = this;
+ var $result = $('<table/>', {class: 'o_group o_inner_group'});
this._handleAttributes($result, node);
this._registerModifiers(node, this.state, $result);
+
+ var col = parseInt(node.attrs.col, 10) || 2;
+
if (node.attrs.string) {
- var $sep = $('<tr><td colspan="2" style="width:100%;"><div class="o_horizontal_separator">' + node.attrs.string + '</div></td></tr>');
+ var $sep = $('<tr><td colspan="' + col + '" style="width: 100%;"><div class="o_horizontal_separator">' + node.attrs.string + '</div></td></tr>');
$result.append($sep);
}
- var children = node.children;
- for (var i = 0; i < children.length; i++) {
- if (children[i].tag === 'field') {
- var fieldNodes = [children[i]];
- if (children[i].attrs.nolabel && children[i+1] &&
- children[i+1].tag === 'field' && children[i+1].attrs.nolabel) {
- fieldNodes.push(children[i+1]);
- i++;
- }
- $result.append(this._renderInnerGroupRow(fieldNodes));
- } else if (children[i].tag === 'label') {
- var label = children[i];
- // If there is a "for" attribute, we expect to have an id concerned in the next node.
- if (label.attrs.for) {
- var linkedNode = children[i+1];
- $result = this._renderInnerGroupLabel($result, label, linkedNode);
- i++; // Skip the rendering of the next node because we just did it.
+
+ var rows = [];
+ var $currentRow = $('<tr/>');
+ var currentColspan = 0;
+ _.each(node.children, function (child) {
+ if (child.tag === 'newline') {
+ rows.push($currentRow);
+ $currentRow = $('<tr/>');
+ currentColspan = 0;
+ return;
+ }
+
+ var colspan = parseInt(child.attrs.colspan, 10);
+ var isLabeledField = (child.tag === 'field' && child.attrs.nolabel !== '1');
+ if (!colspan) {
+ if (isLabeledField) {
+ colspan = 2;
} else {
- $result = this._renderInnerGroupLabel($result, label);
+ colspan = 1;
}
+ }
+ var finalColspan = colspan - (isLabeledField ? 1 : 0);
+ currentColspan += colspan;
+
+ if (currentColspan > col) {
+ rows.push($currentRow);
+ $currentRow = $('<tr/>');
+ currentColspan = colspan;
+ }
+
+ var $tds;
+ if (child.tag === 'field') {
+ $tds = self._renderInnerGroupField(child);
+ } else if (child.tag === 'label') {
+ $tds = self._renderInnerGroupLabel(child);
} else {
- var $td = $('<td colspan="2" style="width:100%;">').append(this._renderNode(children[i]));
- $result.append($('<tr>').append($td));
+ $tds = $('<td/>').append(self._renderNode(child));
}
- }
+ if (finalColspan > 1) {
+ $tds.last().attr('colspan', finalColspan);
+ }
+ $currentRow.append($tds);
+ });
+ rows.push($currentRow);
+
+ _.each(rows, function ($tr) {
+ var nonLabelColSize = 100 / (col - $tr.children('.o_td_label').length);
+ _.each($tr.children(':not(.o_td_label)'), function (el) {
+ var $el = $(el);
+ $el.css('width', ((parseInt($el.attr('colspan'), 10) || 1) * nonLabelColSize) + '%');
+ });
+ $result.append($tr);
+ });
+
return $result;
},
/**
* @private
- * @param {jQueryElement} $result
- * @param {string} label
- * @param {Object} linkedNode
+ * @param {Object} node
* @returns {jQueryElement}
*/
- _renderInnerGroupLabel: function ($result, label, linkedNode) {
- var $first = $('<td class="o_td_label">')
- .append(this._renderNode(label));
- var $second = linkedNode ? $('<td>').append(this._renderNode(linkedNode)) : $('<td>');
- var $tr = $('<tr>').append($first).append($second);
- return $result.append($tr);
+ _renderInnerGroupField: function (node) {
+ var widget = this._renderFieldWidget(node, this.state);
+ var $tds = $('<td/>').append(widget.$el);
+
+ if (node.attrs.nolabel !== '1') {
+ var $labelTd = this._renderInnerGroupLabel(node);
+ $tds = $labelTd.add($tds);
+ }
+
+ return $tds;
},
/**
- * Render a group row, with all the nodes inside.
- *
* @private
- * @param {Object[]} nodes
+ * @param {string} label
* @returns {jQueryElement}
*/
- _renderInnerGroupRow: function (nodes) {
- var $tr = $('<tr>');
- for (var i = 0; i < nodes.length; i++) {
- $tr.append(this._renderInnerField(nodes[i]).contents());
- }
- return $tr;
+ _renderInnerGroupLabel: function (label) {
+ return $('<td/>', {class: 'o_td_label'})
+ .append(this._renderTagLabel(label));
},
/**
* Render a node, from the arch of the view. It is a generic method, that
@@ -537,17 +551,16 @@ var FormRenderer = BasicRenderer.extend({
return this._renderInnerGroup(node);
}
- var $result = $('<div class="o_group"/>');
- var $child;
- _.each(node.children, function (child) {
- if (child.tag === 'group') {
- $child = self._renderInnerGroup(child);
- } else {
- $child = self._renderNode(child);
+ var $result = $('<div/>', {class: 'o_group'});
+ var colSize = Math.max(1, Math.round(12 / (parseInt(node.attrs.col, 10) || 2)));
+ $result.append(_.map(node.children, function (child) {
+ if (child.tag === 'newline') {
+ return $('<br/>');
}
- $child.addClass('o_group_col_6');
- $child.appendTo($result);
- });
+ var $child = self._renderNode(child);
+ $child.addClass('o_group_col_' + (colSize * (parseInt(child.attrs.colspan, 10) || 1)));
+ return $child;
+ }));
this._handleAttributes($result, node);
this._registerModifiers(node, this.state, $result);
return $result;
@@ -575,20 +588,50 @@ var FormRenderer = BasicRenderer.extend({
* @returns {jQueryElement}
*/
_renderTagLabel: function (node) {
+ var self = this;
var text;
+ var fieldName = node.tag === 'label' ? node.attrs.for : node.attrs.name;
if ('string' in node.attrs) { // allow empty string
text = node.attrs.string;
- } else if (node.attrs.for) {
- text = this.state.fields[node.attrs.for].string;
+ } else if (fieldName) {
+ text = this.state.fields[fieldName].string;
} else {
return this._renderGenericTag(node);
}
- var $result = $('<label>')
- .addClass('o_form_label')
- .attr('for', this._getIDForLabel(node.attrs.for))
- .text(text);
- this._handleAttributes($result, node);
- this._registerModifiers(node, this.state, $result);
+ var $result = $('<label>', {
+ class: 'o_form_label',
+ for: this._getIDForLabel(fieldName),
+ text: text,
+ });
+ if (node.tag === 'label') {
+ this._handleAttributes($result, node);
+ }
+ var modifiersOptions;
+ if (fieldName) {
+ modifiersOptions = {
+ callback: function (element, modifiers, record) {
+ var widgets = self.allFieldWidgets[record.id];
+ var widget = _.findWhere(widgets, {name: fieldName});
+ if (!widget) {
+ return; // FIXME this occurs if the widget is created
+ // after the label (explicit <label/> tag in the
+ // arch), so this won't work on first rendering
+ // only on reevaluation
+ }
+ element.$el.toggleClass('o_form_label_empty', !!( // FIXME condition is evaluated twice (label AND widget...)
+ record.data.id
+ && (modifiers.readonly || self.mode === 'readonly')
+ && !widget.isSet()
+ ));
+ },
+ };
+ }
+ // FIXME if the function is called with a <label/> node, the registered
+ // modifiers will be those on this node. Maybe the desired behavior
+ // would be to merge them with associated field node if any... note:
+ // this worked in 10.0 for "o_form_label_empty" reevaluation but not for
+ // "o_invisible_modifier" reevaluation on labels...
+ this._registerModifiers(node, this.state, $result, modifiersOptions);
return $result;
},
/**
@@ -682,6 +725,8 @@ var FormRenderer = BasicRenderer.extend({
return $.when.apply($, defs).then(function () {
self._updateView($form.contents());
+ }, function () {
+ $form.remove();
});
},
/**
@@ -717,7 +762,7 @@ var FormRenderer = BasicRenderer.extend({
}
});
if (focusWidget) {
- focusWidget.activate(true);
+ focusWidget.activate({noselect: true});
}
},
/**
@@ -740,20 +785,26 @@ var FormRenderer = BasicRenderer.extend({
* @private
* @param {OdooEvent} ev
*/
- _onMoveNext: function (ev) {
+ _onNavigationMove: function (ev) {
ev.stopPropagation();
- var index = this.allFieldWidgets[this.state.id].indexOf(ev.target);
- this._activateNextFieldWidget(this.state, index);
+ var index;
+ if (ev.data.direction === "next") {
+ index = this.allFieldWidgets[this.state.id].indexOf(ev.data.target);
+ this._activateNextFieldWidget(this.state, index);
+ } else if (ev.data.direction === "previous") {
+ index = this.allFieldWidgets[this.state.id].indexOf(ev.data.target);
+ this._activatePreviousFieldWidget(this.state, index);
+ }
},
/**
- * @override
+ * open the translation view for the current field
+ *
* @private
- * @param {OdooEvent} event
+ * @param {MouseEvent} ev
*/
- _onMovePrevious: function (ev) {
- ev.stopPropagation();
- var index = this.allFieldWidgets[this.state.id].indexOf(ev.target);
- this._activatePreviousFieldWidget(this.state, index);
+ _onTranslate: function (event) {
+ event.preventDefault();
+ this.trigger_up('translate', {fieldName: event.target.name, id: this.state.id});
},
});
diff --git a/addons/web/static/src/js/views/graph/graph_controller.js b/addons/web/static/src/js/views/graph/graph_controller.js
index 040311a3919..388d390701c 100644
--- a/addons/web/static/src/js/views/graph/graph_controller.js
+++ b/addons/web/static/src/js/views/graph/graph_controller.js
@@ -30,7 +30,7 @@ var GraphController = AbstractController.extend({
destroy: function () {
if (this.$buttons) {
// remove jquery's tooltip() handlers
- this.$buttons.find('button').off();
+ this.$buttons.find('button').off().tooltip('destroy');
}
this._super.apply(this, arguments);
},
diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js
index cce5402e4e5..54e078ab368 100644
--- a/addons/web/static/src/js/views/kanban/kanban_controller.js
+++ b/addons/web/static/src/js/views/kanban/kanban_controller.js
@@ -164,6 +164,7 @@ var KanbanController = BasicController.extend({
var self = this;
this.model.createGroup(event.data.value, this.handle).then(function () {
self.update({}, {reload: false});
+ self._updateButtons();
self.trigger_up('scrollTo', {selector: '.o_column_quick_create'});
});
},
@@ -220,7 +221,7 @@ var KanbanController = BasicController.extend({
var state = this.model.get(this.handle, {raw: true});
var relatedModelName = state.fields[state.groupedBy[0]].relation;
this.model
- .deleteRecords([column.db_id], relatedModelName, this.handle)
+ .deleteRecords([column.db_id], relatedModelName)
.done(function () {
if (column.isEmpty()) {
self.renderer.removeWidget(column);
diff --git a/addons/web/static/src/js/views/kanban/kanban_model.js b/addons/web/static/src/js/views/kanban/kanban_model.js
index 9e5e0fc1267..f3d4d5b3d91 100644
--- a/addons/web/static/src/js/views/kanban/kanban_model.js
+++ b/addons/web/static/src/js/views/kanban/kanban_model.js
@@ -30,7 +30,7 @@ var KanbanModel = BasicModel.extend({
fieldsInfo: group.fieldsInfo,
viewType: group.viewType,
});
- group.data.unshift(new_record);
+ group.data.unshift(new_record.id);
group.count++;
return this._fetchRecord(new_record)
// .then(this._fetch_relational_data.bind(this))
@@ -69,6 +69,7 @@ var KanbanModel = BasicModel.extend({
groupedBy: parent.groupedBy,
isOpen: true,
limit: parent.limit,
+ parentID: parent.id,
openGroupByDefault: true,
orderedBy: parent.orderedBy,
value: result,
@@ -127,7 +128,7 @@ var KanbanModel = BasicModel.extend({
}
return this.notifyChanges(recordID, changes).then(function () {
return self.save(recordID);
- }).then(function (result) {
+ }).then(function () {
// Remove record from its current group
var old_group;
for (var i = 0; i < parent.count; i++) {
@@ -140,7 +141,7 @@ var KanbanModel = BasicModel.extend({
}
}
// Add record to its new group
- new_group.data.push(result.id);
+ new_group.data.push(recordID);
new_group.count++;
return [old_group.id, new_group.id];
});
diff --git a/addons/web/static/src/js/views/kanban/kanban_record.js b/addons/web/static/src/js/views/kanban/kanban_record.js
index 59922c4b005..e5846e55cf4 100644
--- a/addons/web/static/src/js/views/kanban/kanban_record.js
+++ b/addons/web/static/src/js/views/kanban/kanban_record.js
@@ -254,9 +254,8 @@ var KanbanRecord = Widget.extend({
}
attrs[key] = value;
});
- this.fieldsInfo[field_name] = attrs;
-
- var widget = new Widget(this, field_name, this.state, this.options);
+ var options = _.extend({}, this.options, {attrs: attrs});
+ var widget = new Widget(this, field_name, this.state, options);
widget.replace($field);
this._setFieldDisplay(widget.$el, field_name);
return widget;
diff --git a/addons/web/static/src/js/views/kanban/kanban_renderer.js b/addons/web/static/src/js/views/kanban/kanban_renderer.js
index 8152ce4987b..7bfe21e66a9 100644
--- a/addons/web/static/src/js/views/kanban/kanban_renderer.js
+++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js
@@ -269,6 +269,8 @@ var KanbanRenderer = BasicRenderer.extend({
* @private
*/
_renderView: function () {
+ var oldWidgets = this.widgets;
+ this.widgets = [];
var isGrouped = !!this.state.groupedBy.length;
this.$el.toggleClass('o_kanban_grouped', isGrouped);
this.$el.toggleClass('o_kanban_ungrouped', !isGrouped);
@@ -281,7 +283,7 @@ var KanbanRenderer = BasicRenderer.extend({
this._renderUngrouped(fragment);
}
this.$el.append(fragment);
- return this._super.apply(this, arguments);
+ return this._super.apply(this, arguments).then(_.invoke.bind(_, oldWidgets, 'destroy'));
},
});
diff --git a/addons/web/static/src/js/views/list/list_controller.js b/addons/web/static/src/js/views/list/list_controller.js
index f2b15cca349..21e29780d09 100644
--- a/addons/web/static/src/js/views/list/list_controller.js
+++ b/addons/web/static/src/js/views/list/list_controller.js
@@ -156,7 +156,7 @@ var ListController = BasicController.extend({
this.sidebar = new Sidebar(this, {
editable: this.is_action_enabled('edit'),
env: {
- context: this.model.get(this.handle).getContext(),
+ context: this.model.get(this.handle, {raw: true}).getContext(),
activeIds: this.getSelectedIds(),
model: this.modelName,
},
@@ -200,7 +200,7 @@ var ListController = BasicController.extend({
this.model.addDefaultRecord(this.handle, {position: this.editable}).then(function (recordID) {
self._toggleNoContentHelper(false);
var state = self.model.get(self.handle);
- self.renderer.updateState(state);
+ self.renderer.updateState(state, {});
self.renderer.editRecord(recordID);
});
},
@@ -231,13 +231,14 @@ var ListController = BasicController.extend({
*/
_confirmSave: function (id) {
var state = this.model.get(this.handle);
- return this.renderer.confirmSave(state, id);
+ return this.renderer.updateState(state, {noRender: true})
+ .then(this._setMode.bind(this, 'readonly', id));
},
/**
* @override
* @private
*/
- _getSidebarEnv: function() {
+ _getSidebarEnv: function () {
var env = this._super.apply(this, arguments);
var record = this.model.get(this.handle);
return _.extend(env, {domain: record.getDomain()});
@@ -249,12 +250,14 @@ var ListController = BasicController.extend({
* @private
* @param {string} mode
* @param {string} [recordID] - default to main recordID
+ * @returns {Deferred}
*/
_setMode: function (mode, recordID) {
- this._super.apply(this, arguments);
if ((recordID || this.handle) !== this.handle) {
- this.renderer.setRowMode(recordID, mode);
this._updateButtons(mode);
+ return this.renderer.setRowMode(recordID, mode);
+ } else {
+ return this._super.apply(this, arguments);
}
},
/**
@@ -272,6 +275,7 @@ var ListController = BasicController.extend({
* @returns {Deferred}
*/
_update: function (state) {
+ this.selectedRecords = [];
this._toggleNoContentHelper(!this._hasContent(state));
this._toggleSidebar();
return this._super.apply(this, arguments);
@@ -356,7 +360,8 @@ var ListController = BasicController.extend({
*/
_onEditLine: function (ev) {
ev.stopPropagation();
- this._setMode('edit', ev.data.recordID);
+ this._setMode('edit', ev.data.recordID)
+ .done(ev.data.onSuccess);
},
/**
* Opens the Export Dialog
diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js
index 1b662fa46af..a857fee7103 100644
--- a/addons/web/static/src/js/views/list/list_editable_renderer.js
+++ b/addons/web/static/src/js/views/list/list_editable_renderer.js
@@ -18,11 +18,7 @@ var _t = core._t;
ListRenderer.include({
custom_events: _.extend({}, ListRenderer.prototype.custom_events, {
- move_down: '_onMoveDown',
- move_up: '_onMoveUp',
- move_left: '_onMoveLeft',
- move_right: '_onMoveRight',
- move_next_line: '_onMoveNextLine',
+ navigation_move: '_onNavigationMove',
}),
events: _.extend({}, ListRenderer.prototype.events, {
'click tbody td.o_data_cell': '_onCellClick',
@@ -48,8 +44,6 @@ ListRenderer.include({
// of each line, so the user can delete a record.
this.addTrashIcon = params.addTrashIcon;
- this.editable = this.arch.attrs.editable;
-
this.currentRow = null;
this.currentCol = null;
},
@@ -90,20 +84,6 @@ ListRenderer.include({
return this._super(recordID);
},
/**
- * This method is called by the controller when the user has clicked 'save',
- * and the model as actually saved the current changes. We then need to
- * set the correct values for each cell. The difference with confirmChange
- * is that the edited line is now in readonly mode, so we can just set its
- * new value.
- *
- * @param {Object} state the new full state for the list
- * @param {string} savedRecordID the id for the saved record
- */
- confirmSave: function (state, savedRecordID) {
- this.state = state;
- this.setRowMode(savedRecordID, 'readonly');
- },
- /**
* Edit a given record in the list
*
* @param {string} recordID
@@ -147,6 +127,7 @@ ListRenderer.include({
*
* @param {string} recordID
* @param {string} mode
+ * @returns {Deferred}
*/
setRowMode: function (recordID, mode) {
var self = this;
@@ -159,40 +140,67 @@ ListRenderer.include({
this.currentRow = editMode ? rowIndex : null;
var $row = this.$('.o_data_row:nth(' + rowIndex + ')');
+ var $tds = $row.children('.o_data_cell');
+ var oldWidgets = _.clone(this.allFieldWidgets[record.id]);
+ // When switching to edit mode, force the dimensions of all cells to
+ // their current value so that they won't change if their content
+ // changes, to prevent the view from flickering.
if (editMode) {
- // Instantiate column widgets and destroy potential readonly ones
- var oldWidgets = _.clone(this.allFieldWidgets[record.id]);
- var $tds = $row.children('.o_data_cell');
- // Force the size of each cell to its current value so that it
- // won't change if its content changes, to prevent the view from
- // flickering
$tds.each(function () {
var $td = $(this);
$td.css({width: $td.outerWidth()});
});
- _.each(this.columns, function (node, colIndex) {
- var $td = $tds.eq(colIndex);
- var $newTd = self._renderBodyCell(record, node, colIndex, {
- renderInvisible: true,
- renderWidgets: true,
- });
-
- // TODO this is ugly...
- if ($td.hasClass('o_list_button')) {
- self._unregisterModifiersElement(node, record, $td.children());
- }
+ }
+
+ // Prepare options for cell rendering (this depends on the mode)
+ var options = {
+ renderInvisible: editMode,
+ renderWidgets: editMode,
+ };
+ if (!editMode) {
+ // Force 'readonly' mode for widgets in readonly rows as
+ // otherwise they default to the view mode which is 'edit' for
+ // an editable list view
+ options.mode = 'readonly';
+ }
+ // Switch each cell to the new mode; note: the '_renderBodyCell'
+ // function might fill the 'this.defs' variables with multiple deferred
+ // so we create the array and delete it after the rendering.
+ var defs = [];
+ this.defs = defs;
+ _.each(this.columns, function (node, colIndex) {
+ var $td = $tds.eq(colIndex);
+ var $newTd = self._renderBodyCell(record, node, colIndex, options);
+
+ // Widgets are unregistered of modifiers data when they are
+ // destroyed. This is not the case for simple buttons so we have to
+ // do it here.
+ if ($td.hasClass('o_list_button')) {
+ self._unregisterModifiersElement(node, record, $td.children());
+ }
+
+ // For edit mode we only replace the content of the cell with its
+ // new content (invisible fields, editable fields, ...).
+ // For readonly mode, we replace the whole cell so that the
+ // dimensions of the cell are not forced anymore.
+ if (editMode) {
$td.empty().append($newTd.contents());
- });
- _.each(oldWidgets, this._destroyFieldWidget.bind(this, record));
- } else {
- for (var colIndex = 0; colIndex < this.columns.length; colIndex++) {
- this._setCellValue(rowIndex, colIndex);
+ } else {
+ self._unregisterModifiersElement(node, record, $td);
+ $td.replaceWith($newTd);
}
- }
+ });
+ delete this.defs;
+
+ // Destroy old field widgets
+ _.each(oldWidgets, this._destroyFieldWidget.bind(this, record));
+
+ // Toggle selected class here so that style is applied at the end
+ $row.toggleClass('o_selected_row', editMode);
- $row.toggleClass('o_selected_row', editMode); // Toggle here so that style is applied at the end
+ return $.when.apply($, defs);
},
//--------------------------------------------------------------------------
@@ -214,7 +222,30 @@ ListRenderer.include({
return n;
},
/**
- * Move the cursor one the beginning of the next line, if possible.
+ * Returns true iff the list is editable, i.e. if it isn't grouped and if
+ * the editable attribute is set on the root node of its arch.
+ *
+ * @private
+ * @returns {boolean}
+ */
+ _isEditable: function () {
+ return this.mode === 'edit' && !this.state.groupedBy.length && this.arch.attrs.editable;
+ },
+ /**
+ * Move the cursor on the end of the previous line, if possible.
+ * If there is no previous line, then we create a new record.
+ *
+ * @private
+ */
+ _moveToPreviousLine: function () {
+ if (this.currentRow > 0) {
+ this._selectCell(this.currentRow - 1, this.columns.length - 1);
+ } else {
+ this._unselectRow().then(this.trigger_up.bind(this, 'add_record'));
+ }
+ },
+ /**
+ * Move the cursor on the beginning of the next line, if possible.
* If there is no next line, then we create a new record.
*
* @private
@@ -223,9 +254,7 @@ ListRenderer.include({
if (this.currentRow < this.state.data.length - 1) {
this._selectCell(this.currentRow + 1, 0);
} else {
- this._unselectRow().then(
- this.trigger_up.bind(this, 'add_record')
- );
+ this._unselectRow().then(this.trigger_up.bind(this, 'add_record'));
}
},
/**
@@ -313,24 +342,31 @@ ListRenderer.include({
*
* @param {integer} rowIndex
* @param {integer} colIndex
- * @param {boolean} [wrap=true] if true and no widget could be selected from
- * the colIndex to the last column, then we wrap around and try to select
- * a widget starting from the beginning
+ * @param {Object} [options]
+ * @param {Event} [options.event] original target of the event which
+ * @param {boolean} [options.wrap=true] if true and no widget could be
+ * triggered the cell selection
+ * selected from the colIndex to the last column, then we wrap around and
+ * try to select a widget starting from the beginning
* @return {Deferred} fails if no cell could be selected
*/
- _selectCell: function (rowIndex, colIndex, wrap) {
+ _selectCell: function (rowIndex, colIndex, options) {
// Do nothing if the user tries to select current cell
if (rowIndex === this.currentRow && colIndex === this.currentCol) {
return $.when();
}
- wrap = wrap === undefined ? true : wrap;
+ var wrap = (!options || options.wrap === undefined) ? true : options.wrap;
// Select the row then activate the widget in the correct cell
var self = this;
return this._selectRow(rowIndex).then(function () {
var record = self.state.data[rowIndex];
var correctedIndex = colIndex - getNbButtonBefore(colIndex);
- var fieldIndex = self._activateFieldWidget(record, correctedIndex, {inc: 1, wrap: wrap});
+ var fieldIndex = self._activateFieldWidget(record, correctedIndex, {
+ inc: 1,
+ wrap: wrap,
+ event: options && options.event,
+ });
if (fieldIndex < 0) {
return $.Deferred().reject();
@@ -353,6 +389,7 @@ ListRenderer.include({
* Activates the row at the given row index.
*
* @param {integer} rowIndex
+ * @returns {Deferred}
*/
_selectRow: function (rowIndex) {
// Do nothing if already selected
@@ -365,41 +402,15 @@ ListRenderer.include({
return this._unselectRow().then(function () {
// Notify the controller we want to make a record editable
var record = self.state.data[rowIndex];
+ var def = $.Deferred();
self.trigger_up('edit_line', {
recordID: record.id,
+ onSuccess: def.resolve.bind(def),
});
+ return def;
});
},
/**
- * Set the value of a cell. This method can be called when the value of a
- * cell was modified, for example after an onchange.
- *
- * @param {integer} rowIndex
- * @param {integer} colIndex
- */
- _setCellValue: function (rowIndex, colIndex) {
- var record = this.state.data[rowIndex];
- var node = this.columns[colIndex];
-
- var $oldTd = this.$('.o_data_row:nth(' + rowIndex + ') > .o_data_cell:nth(' + colIndex + ')');
- var $newTd = this._renderBodyCell(record, node, colIndex, {mode: 'readonly'});
- this._unregisterModifiersElement(node, record, $oldTd);
- $oldTd.replaceWith($newTd);
-
- // Destroy old cell field widget if any
- // TODO this is very inefficient O(n^3) instead of O(n) on row update
- // because this method is called for each cell (O(n)), each time we have
- // to find the associated record widget (O(n)) and once found, the
- // search is performed again by the _destroyFieldWidget function
- if (node.tag === 'field') {
- var recordWidgets = this.allFieldWidgets[record.id];
- var w = _.findWhere(recordWidgets, {name: node.attrs.name}); //
- if (w) {
- this._destroyFieldWidget(record, w);
- }
- }
- },
- /**
* This method is called whenever we click/move outside of a row that was
* in edit mode. This is the moment we save all accumulated changes on that
* row, if needed (@see BasicController.saveRecord).
@@ -471,19 +482,19 @@ ListRenderer.include({
_onCellClick: function (event) {
// The special_click property explicitely allow events to bubble all
// the way up to bootstrap's level rather than being stopped earlier.
- if (this.mode === 'readonly' || !this.editable || $(event.target).prop('special_click')) {
+ if (!this._isEditable() || $(event.target).prop('special_click')) {
return;
}
var $td = $(event.currentTarget);
var $tr = $td.parent();
var rowIndex = this.$('.o_data_row').index($tr);
var colIndex = $tr.find('.o_data_cell').index($td);
- this._selectCell(rowIndex, colIndex);
+ this._selectCell(rowIndex, colIndex, {event: event});
},
/**
* We need to manually unselect row, because noone else would do it
*/
- _onEmptyRowClick: function (event) {
+ _onEmptyRowClick: function () {
this._unselectRow();
},
/**
@@ -495,78 +506,68 @@ ListRenderer.include({
this._unselectRow();
},
/**
- * Move the cursor on the cell just down the current cell.
- */
- _onMoveDown: function () {
- if (this.currentRow < this.state.data.length - 1) {
- this._selectCell(this.currentRow + 1, this.currentCol);
- }
- },
- /**
- * Move the cursor on the left, if possible
- */
- _onMoveLeft: function () {
- if (this.currentCol > 0) {
- this._selectCell(this.currentRow, this.currentCol - 1);
- }
- },
- /**
- * Move the cursor on the next available cell, so either the next available
- * cell on the right, or the first on the next line. This method is called
- * when the user press the TAB key.
+ * Handles the keyboard navigation according to events triggered by field
+ * widgets.
+ * - up/down: move to the cell above/below if any, or the first activable
+ * one on the row above/below if any on the right of this cell
+ * above/below (if none on the right, wrap to the beginning of the
+ * line).
+ * - left/right: move to the first activable cell on the left/right if any
+ * (wrap to the end/beginning of the line if necessary).
+ * - previous: move to the first activable cell on the left if any, if not
+ * move to the rightmost activable cell on the row above.
+ * - next: move to the first activable cell on the right if any, if not move
+ * to the leftmost activable cell on the row below.
+ * - next_line: move to leftmost activable cell on the row below.
*
- * @param {OdooEvent} ev
- */
- _onMoveNext: function (ev) {
- // we need to stop the event, to prevent interference with some other
- // component up there, such as a form renderer.
- ev.stopPropagation();
- if (this.currentCol + 1 < this.columns.length) {
- this._selectCell(this.currentRow, this.currentCol + 1, false)
- .fail(this._moveToNextLine.bind(this));
- } else {
- this._moveToNextLine();
- }
- },
- /**
- * @private
- * @param {OdooEvent} event
- */
- _onMoveNextLine: function (event) {
- event.stopPropagation();
- this._moveToNextLine();
- },
- /**
- * Move the cursor on the previous available cell, so either the previous
- * available cell on the left, or the last on the previous line. This method
- * is called when the user press the TAB key while holding the shift key.
+ * Note: moving to a line below if on the last line or moving to a line
+ * above if on the first line automatically creates a new line.
*
+ * @private
* @param {OdooEvent} ev
*/
- _onMovePrevious: function (ev) {
- // we need to stop the event, to prevent interference with some other
- // component up there, such as a form renderer.
- ev.stopPropagation();
- if (this.currentCol > 0) {
- this._selectCell(this.currentRow, this.currentCol - 1);
- } else if (this.currentRow > 0) {
- this._selectCell(this.currentRow - 1, this.columns.length - 1);
- }
- },
- /**
- * Move the cursor one cell right, if possible
- */
- _onMoveRight: function () {
- if (this.currentCol + 1 < this.columns.length) {
- this._selectCell(this.currentRow, this.currentCol + 1);
- }
- },
- /**
- * Move the cursor one line up
- */
- _onMoveUp: function () {
- if (this.currentRow > 0) {
- this._selectCell(this.currentRow - 1, this.currentCol);
+ _onNavigationMove: function (ev) {
+ ev.stopPropagation(); // stop the event, the action is done by this renderer
+ switch (ev.data.direction) {
+ case 'up':
+ if (this.currentRow > 0) {
+ this._selectCell(this.currentRow - 1, this.currentCol);
+ }
+ break;
+ case 'right':
+ if (this.currentCol + 1 < this.columns.length) {
+ this._selectCell(this.currentRow, this.currentCol + 1);
+ }
+ break;
+ case 'down':
+ if (this.currentRow < this.state.data.length - 1) {
+ this._selectCell(this.currentRow + 1, this.currentCol);
+ }
+ break;
+ case 'left':
+ if (this.currentCol > 0) {
+ this._selectCell(this.currentRow, this.currentCol - 1);
+ }
+ break;
+ case 'previous':
+ if (this.currentCol > 0) {
+ this._selectCell(this.currentRow, this.currentCol - 1, {wrap: false})
+ .fail(this._moveToPreviousLine.bind(this));
+ } else {
+ this._moveToPreviousLine();
+ }
+ break;
+ case 'next':
+ if (this.currentCol + 1 < this.columns.length) {
+ this._selectCell(this.currentRow, this.currentCol + 1, {wrap: false})
+ .fail(this._moveToNextLine.bind(this));
+ } else {
+ this._moveToNextLine();
+ }
+ break;
+ case 'next_line':
+ this._moveToNextLine();
+ break;
}
},
/**
@@ -577,7 +578,7 @@ ListRenderer.include({
* @private
*/
_onRowClicked: function () {
- if (this.mode === 'readonly' || !this.editable) {
+ if (!this._isEditable()) {
this._super.apply(this, arguments);
}
},
diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js
index 3cda7e9f809..21028b99e02 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -246,10 +246,12 @@ var ListRenderer = BasicRenderer.extend({
if (node.tag === 'button') {
tdClassName += ' o_list_button';
} else {
- if (node.attrs.widget){
+ var typeClass = FIELD_CLASSES[this.state.fields[node.attrs.name].type];
+ if (typeClass) {
+ tdClassName += (' ' + typeClass);
+ }
+ if (node.attrs.widget) {
tdClassName += (' o_' + node.attrs.widget + '_cell');
- } else {
- tdClassName += (' ' + FIELD_CLASSES[this.state.fields[node.attrs.name].type]);
}
}
var $td = $('<td>', {class: tdClassName});
@@ -268,9 +270,7 @@ var ListRenderer = BasicRenderer.extend({
return $td.append(this._renderButton(record, node));
}
if (node.attrs.widget || (options && options.renderWidgets)) {
- this.defs = []; // TODO maybe wait for those somewhere ?
var widget = this._renderFieldWidget(node, record, _.pick(options, 'mode'));
- delete this.defs;
return $td.append(widget.$el);
}
var name = node.attrs.name;
@@ -534,9 +534,11 @@ var ListRenderer = BasicRenderer.extend({
*/
_renderRow: function (record) {
var self = this;
+ this.defs = []; // TODO maybe wait for those somewhere ?
var $cells = _.map(this.columns, function (node, index) {
return self._renderBodyCell(record, node, index, {mode: 'readonly'});
});
+ delete this.defs;
var className = 'o_data_row';
var decorations = this._computeDecorationClassNames(record);
if (decorations.length) {
diff --git a/addons/web/static/src/js/views/pivot/pivot_renderer.js b/addons/web/static/src/js/views/pivot/pivot_renderer.js
index c38f8b6b768..a37e65b104b 100644
--- a/addons/web/static/src/js/views/pivot/pivot_renderer.js
+++ b/addons/web/static/src/js/views/pivot/pivot_renderer.js
@@ -7,6 +7,9 @@ var field_utils = require('web.field_utils');
var PivotRenderer = AbstractRenderer.extend({
tagName: 'table',
className: 'table-hover table-condensed table-bordered',
+ events: _.extend({}, AbstractRenderer.prototype.events, {
+ 'hover td': '_onTdHover',
+ }),
//--------------------------------------------------------------------------
// Private
@@ -34,9 +37,6 @@ var PivotRenderer = AbstractRenderer.extend({
}
this._renderHeaders($thead, this.state.headers);
this._renderRows($tbody, this.state.rows);
- $table.on('hover', 'td', function () {
- $table.find('col:eq(' + $(this).index()+')').toggleClass('hover');
- });
// todo: make sure the next line does something
$table.find('.o_pivot_header_cell_opened,.o_pivot_header_cell_closed').tooltip();
this.$el.html($table.contents());
@@ -139,6 +139,19 @@ var PivotRenderer = AbstractRenderer.extend({
}
},
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {MouseEvent} event
+ */
+ _onTdHover: function (event) {
+ var $td = $(event.target);
+ $td.closest('table').find('col:eq(' + $td.index()+')').toggleClass('hover');
+ }
+
});
return PivotRenderer;
diff --git a/addons/web/static/src/js/views/view_dialogs.js b/addons/web/static/src/js/views/view_dialogs.js
index d0c1fa75fdf..7e20cd74d04 100644
--- a/addons/web/static/src/js/views/view_dialogs.js
+++ b/addons/web/static/src/js/views/view_dialogs.js
@@ -19,6 +19,9 @@ var _t = core._t;
var ViewDialog = Dialog.extend({
custom_events: _.extend({}, Dialog.prototype.custom_events, {
push_state: '_onPushState',
+ env_updated: function (event) {
+ event.stopPropagation();
+ },
}),
/**
* @constructor
diff --git a/addons/web/static/src/js/widgets/date_picker.js b/addons/web/static/src/js/widgets/date_picker.js
index 1aaf05ee11e..353a5dc78f2 100644
--- a/addons/web/static/src/js/widgets/date_picker.js
+++ b/addons/web/static/src/js/widgets/date_picker.js
@@ -12,10 +12,13 @@ var DateWidget = Widget.extend({
template: "web.datepicker",
type_of_date: "date",
events: {
- 'dp.change': 'change_datetime',
- 'dp.show': 'set_datetime_default',
- 'change .o_datepicker_input': 'change_datetime',
+ 'dp.change': 'changeDatetime',
+ 'dp.show': '_onShow',
+ 'change .o_datepicker_input': 'changeDatetime',
},
+ /**
+ * @override
+ */
init: function(parent, options) {
this._super.apply(this, arguments);
@@ -41,6 +44,9 @@ var DateWidget = Widget.extend({
keyBinds: null,
});
},
+ /**
+ * @override
+ */
start: function() {
this.$input = this.$('input.o_datepicker_input');
this.$input.focus(function(e) {
@@ -49,67 +55,120 @@ var DateWidget = Widget.extend({
this.$input.datetimepicker(this.options);
this.picker = this.$input.data('DateTimePicker');
this.$input.click(this.picker.toggle.bind(this.picker));
- this.set_readonly(false);
+ this._setReadonly(false);
},
- set_value: function(value) {
- this.set({'value': value});
- var formatted_value = value ? this.format_client(value) : null;
- this.$input.val(formatted_value);
- if (this.picker) {
- this.picker.date(formatted_value);
+ /**
+ * @override
+ */
+ destroy: function() {
+ this.picker.destroy();
+ this._super.apply(this, arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * set datetime value
+ */
+ changeDatetime: function () {
+ if(this.isValid()) {
+ this._setValueFromUi();
+ this.trigger("datetime_changed");
}
},
- get_value: function() {
+ /**
+ * @returns {Moment|false}
+ */
+ getValue: function () {
var value = this.get('value');
return value && value.clone();
},
- set_value_from_ui: function() {
- var value = this.$input.val() || false;
- this.set_value(this.parse_client(value));
- },
- set_readonly: function(readonly) {
- this.readonly = readonly;
- this.$input.prop('readonly', this.readonly);
- },
- is_valid: function() {
+ /**
+ * @returns {boolean}
+ */
+ isValid: function () {
var value = this.$input.val();
if(value === "") {
return true;
} else {
try {
- this.parse_client(value);
+ this._parseClient(value);
return true;
} catch(e) {
return false;
}
}
},
- parse_client: function(v) {
- return field_utils.parse[this.type_of_date](v, null, {timezone: false});
+ /**
+ * @param {Moment|false}
+ */
+ setValue: function (value) {
+ this.set({'value': value});
+ var formatted_value = value ? this._formatClient(value) : null;
+ this.$input.val(formatted_value);
+ if (this.picker) {
+ this.picker.date(value || null);
+ }
},
- format_client: function(v) {
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {Moment}
+ * @returns {string}
+ */
+ _formatClient: function (v) {
return field_utils.format[this.type_of_date](v, null, {timezone: false});
},
- set_datetime_default: function() {
+ /**
+ * @private
+ * @param {string|false}
+ * @returns {Moment}
+ */
+ _parseClient: function (v) {
+ return field_utils.parse[this.type_of_date](v, null, {timezone: false});
+ },
+ /**
+ * @private
+ * @param {boolean}
+ */
+ _setReadonly: function (readonly) {
+ this.readonly = readonly;
+ this.$input.prop('readonly', this.readonly);
+ },
+ /**
+ * set the value from the input value
+ *
+ * @private
+ */
+ _setValueFromUi: function() {
+ var value = this.$input.val() || false;
+ this.setValue(this._parseClient(value));
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * set the date of the picker by the current date or the today date
+ *
+ * @private
+ */
+ _onShow: function () {
//when opening datetimepicker the date and time by default should be the one from
//the input field if any or the current day otherwise
var value = moment().second(0);
- if(this.$input.val().length !== 0 && this.is_valid()) {
- value = this.$input.val();
+ if(this.$input.val().length !== 0 && this.isValid()) {
+ value = this._parseClient(this.$input.val());
}
-
this.picker.date(value);
},
- change_datetime: function() {
- if(this.is_valid()) {
- this.set_value_from_ui();
- this.trigger("datetime_changed");
- }
- },
- destroy: function() {
- this.picker.destroy();
- this._super.apply(this, arguments);
- },
});
var DateTimeWidget = DateWidget.extend({
diff --git a/addons/web/static/src/js/widgets/debug_manager.js b/addons/web/static/src/js/widgets/debug_manager.js
index cdb3236aa64..badff89c846 100644
--- a/addons/web/static/src/js/widgets/debug_manager.js
+++ b/addons/web/static/src/js/widgets/debug_manager.js
@@ -168,6 +168,7 @@ var DebugManager = Widget.extend({
res_model: 'ir.ui.view',
title: _t('Select a view'),
disable_multiple_selection: true,
+ domain: [['type', '!=', 'qweb'], ['type', '!=', 'search']],
on_selected: function (element_ids) {
self._rpc({
model: 'ir.ui.view',
diff --git a/addons/web/static/src/js/widgets/domain_selector.js b/addons/web/static/src/js/widgets/domain_selector.js
index 8bbebb3cdf9..74572e81b39 100644
--- a/addons/web/static/src/js/widgets/domain_selector.js
+++ b/addons/web/static/src/js/widgets/domain_selector.js
@@ -660,9 +660,9 @@ var DomainLeaf = DomainNode.extend({
this.valueWidget = new (selectedField.type === "datetime" ? datepicker.DateTimeWidget : datepicker.DateWidget)(this);
wDefs.push(this.valueWidget.appendTo("<div/>").then((function () {
this.valueWidget.$el.addClass("o_domain_leaf_value_input");
- this.valueWidget.set_value(moment(this.value));
+ this.valueWidget.setValue(moment(this.value));
this.valueWidget.on("datetime_changed", this, function () {
- this._changeValue(this.valueWidget.get_value());
+ this._changeValue(this.valueWidget.getValue());
});
}).bind(this)));
}
diff --git a/addons/web/static/src/less/fields.less b/addons/web/static/src/less/fields.less
index 329b4f62fbd..b070a8f4cc8 100644
--- a/addons/web/static/src/less/fields.less
+++ b/addons/web/static/src/less/fields.less
@@ -26,7 +26,11 @@
//------------------------------------------------------------------------------
.o_field_widget {
- display: inline-block;
+ // Default display and alignment of widget and internal <input/>
+ &, input.o_input {
+ display: inline-block;
+ text-align: inherit;
+ }
// Block fields
&.note-editor, &.oe_form_field_html, &.oe_form_field_html_text, &.oe_form_field_text, &.o_view_manager_content, &.o_field_domain {
@@ -64,11 +68,6 @@
}
}
- // Input in field
- input[type="text"] {
- display: inline-block;
- }
-
// Text
&.o_field_text, &.oe_form_field_text .oe_form_text_content {
width: 100%;
@@ -92,6 +91,18 @@
.o-flex-flow(row, wrap);
.o-align-items(baseline);
+ .o_tag_color_0 { background-color: #4D4D4D; }
+ .o_tag_color_1 { background-color: #61BD4F; }
+ .o_tag_color_2 { background-color: #F2D600; }
+ .o_tag_color_3 { background-color: #FFAB4A; }
+ .o_tag_color_4 { background-color: #EB5A46; }
+ .o_tag_color_5 { background-color: #875A7B; }
+ .o_tag_color_6 { background-color: #0079BF; }
+ .o_tag_color_7 { background-color: #00C2E0; }
+ .o_tag_color_8 { background-color: #4CD98E; }
+ .o_tag_color_9 { background-color: #FF80CE; }
+ .o_tag_color_10 { background-color: #B6BBBF; }
+
> .o_field_widget {
.o-flex(1, 0, 100px);
position: initial;
@@ -105,18 +116,6 @@
color: white;
cursor: pointer;
- &.o_tag_color_0 { background-color: #4D4D4D; }
- &.o_tag_color_1 { background-color: #61BD4F; }
- &.o_tag_color_2 { background-color: #F2D600; }
- &.o_tag_color_3 { background-color: #FFAB4A; }
- &.o_tag_color_4 { background-color: #EB5A46; }
- &.o_tag_color_5 { background-color: #875A7B; }
- &.o_tag_color_6 { background-color: #0079BF; }
- &.o_tag_color_7 { background-color: #00C2E0; }
- &.o_tag_color_8 { background-color: #4CD98E; }
- &.o_tag_color_9 { background-color: #FF80CE; }
- &.o_tag_color_10 { background-color: #B6BBBF; }
-
> .o_badge_text {
.o-text-overflow(inline-block);
max-width: 200px;
diff --git a/addons/web/static/src/less/list_view.less b/addons/web/static/src/less/list_view.less
index 0caa775add3..eaf0f1bfba8 100644
--- a/addons/web/static/src/less/list_view.less
+++ b/addons/web/static/src/less/list_view.less
@@ -92,11 +92,11 @@
// Values styling
.o_data_cell {
- &.o_list_number, &.o_field_integer, &.o_field_float, &.o_field_monetary {
+ &.o_list_number {
text-align: right;
white-space: nowrap;
}
- &.o_list_text, &.o_field_text {
+ &.o_list_text {
white-space: pre-wrap;
}
&.o_invisible_modifier {
@@ -174,9 +174,6 @@
.o_field_boolean {
width: auto!important; // Override the width computed in JS (needed for Chrome)
}
- .o_field_number {
- text-align: right;
- }
}
}
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index d89d11f0cd5..b9b7caeea7d 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1173,7 +1173,7 @@
<t t-name="M2ODialog">
<div>
<p/>
- Name: <input class="oe_form_m2o_input_name" type="text"/>
+ Name: <input class="o_input" type="text"/>
</div>
</t>
<t t-name="FieldMany2ManyCheckBoxes">
@@ -1219,7 +1219,7 @@
</t>
<t t-name="notification-box">
- <div t-att-class="'alert alert-dismissible alert-' + type" role="alert">
+ <div t-attf-class="o_notification_box alert alert-dismissible alert-{{type}}" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true" class="fa fa-times"></span>
</button>
diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js
index c1fb007b937..7b9fbd061eb 100644
--- a/addons/web/static/tests/fields/basic_fields_tests.js
+++ b/addons/web/static/tests/fields/basic_fields_tests.js
@@ -123,7 +123,7 @@ QUnit.module('basic_fields', {
QUnit.module('FieldBoolean');
QUnit.test('boolean field in form view', function (assert) {
- assert.expect(11);
+ assert.expect(12);
var form = createView({
View: FormView,
@@ -183,6 +183,12 @@ QUnit.module('basic_fields', {
.trigger({type: "keyup", which: $.ui.keyCode.ENTER});
assert.strictEqual(form.$('.o_field_boolean input:checked').length, 1,
"checkbox should now be checked");
+ // blindly press enter again, it should uncheck the checkbox
+ $(document.activeElement).trigger({type: "keydown", which: $.ui.keyCode.ENTER});
+ assert.strictEqual(form.$('.o_field_boolean input:checked').length, 0,
+ "checkbox should not be checked");
+ // blindly press enter again, it should check the checkbox back
+ $(document.activeElement).trigger({type: "keydown", which: $.ui.keyCode.ENTER});
// save
form.$buttons.find('.o_form_button_save').click();
@@ -237,10 +243,10 @@ QUnit.module('basic_fields', {
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input:checked').length, 3,
"should still have only 3 checked input");
- // Re-Edit the line to check the checkbox back
+ // Re-Edit the line to check the checkbox back but this time click on
+ // the checkbox directly in readonly mode !
$cell = list.$('tr.o_data_row:has(.o_checkbox input:not(:checked)) td:not(.o_list_record_selector)').first();
- $cell.click();
- $cell.find('.o_checkbox input:not(:checked)').click();
+ $cell.find('.o_checkbox span').click();
// save
list.$buttons.find('.o_form_button_save').click();
@@ -415,9 +421,9 @@ QUnit.module('basic_fields', {
'</tree>',
});
- var zeroValues = list.$('td').filter(function () {return $(this).text() === '0.000';});
- assert.strictEqual(zeroValues.length, 2,
- 'Unset float values should be rendered as zeros.');
+ var zeroValues = list.$('td.o_data_cell').filter(function () {return $(this).text() === '';});
+ assert.strictEqual(zeroValues.length, 1,
+ 'Unset float values should be rendered as empty strings.');
// switch to edit mode
var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector)').first();
@@ -441,8 +447,8 @@ QUnit.module('basic_fields', {
QUnit.test('do not trigger a field_changed if they have not changed', function (assert) {
assert.expect(2);
- this.data.partner.records[1].qux = undefined;
- this.data.partner.records[1].int_field = undefined;
+ this.data.partner.records[1].qux = false;
+ this.data.partner.records[1].int_field = false;
var form = createView({
View: FormView,
model: 'partner',
@@ -656,7 +662,7 @@ QUnit.module('basic_fields', {
this.data.partner.fields.foo.translate = true;
- var multi_lang = _t.database.multi_lang;
+ var multiLang = _t.database.multi_lang;
_t.database.multi_lang = true;
var form = createView({
@@ -701,7 +707,7 @@ QUnit.module('basic_fields', {
assert.strictEqual($button.length, 0, "should not have a translate button in create mode");
form.destroy();
- _t.database.multi_lang = multi_lang;
+ _t.database.multi_lang = multiLang;
});
@@ -869,7 +875,7 @@ QUnit.module('basic_fields', {
this.data.partner.fields.txt.translate = true;
- var multi_lang = _t.database.multi_lang;
+ var multiLang = _t.database.multi_lang;
_t.database.multi_lang = true;
var form = createView({
@@ -914,7 +920,7 @@ QUnit.module('basic_fields', {
assert.strictEqual($button.length, 0, "should not have a translate button in create mode");
form.destroy();
- _t.database.multi_lang = multi_lang;
+ _t.database.multi_lang = multiLang;
});
QUnit.module('FieldBinary');
@@ -1141,12 +1147,12 @@ QUnit.module('basic_fields', {
"graph of first record should be a barchart");
assert.strictEqual(kanban.$('.o_kanban_record:nth(1) .o_graph_linechart').length, 1,
"graph of second record should be a linechart");
-
+
var evt = document.createEvent("MouseEvents"); //taken ref from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
evt.initMouseEvent("mouseover", true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
- $('.discreteBar')[0].dispatchEvent(evt)
+ $('.discreteBar')[0].dispatchEvent(evt);
var tooltip = $('.nvtooltip').find('table').find('.key')[0].innerText;
- assert.equal(tooltip,graph_key, "graph tooltip should be generated ")
+ assert.equal(tooltip,graph_key, "graph tooltip should be generated ");
$('.nvtooltip').remove();
// force a re-rendering of the first record (to check if the
@@ -1251,7 +1257,7 @@ QUnit.module('basic_fields', {
});
QUnit.test('date field in form view', function (assert) {
- assert.expect(7);
+ assert.expect(8);
var form = createView({
View: FormView,
@@ -1284,6 +1290,7 @@ QUnit.module('basic_fields', {
// click on the input and select another value
form.$('.o_datepicker_input').click();
assert.ok(form.$('.bootstrap-datetimepicker-widget').length, 'datepicker should be open');
+ assert.strictEqual(form.$('.day.active').data('day'), '02/03/2017', 'datepicker should be highlight February 3');
form.$('.bootstrap-datetimepicker-widget .picker-switch').first().click(); // Month selection
form.$('.bootstrap-datetimepicker-widget .picker-switch').first().click(); // Year selection
form.$('.bootstrap-datetimepicker-widget .year:contains(2017)').click();
@@ -1387,7 +1394,6 @@ QUnit.module('basic_fields', {
form.destroy();
});
-
QUnit.module('FieldDatetime');
QUnit.test('datetime field in form view', function (assert) {
@@ -1659,9 +1665,9 @@ QUnit.module('basic_fields', {
assert.strictEqual(euroValues.length, 1,
'One one line has euro as a currency.');
- var zeroValues = list.$('td').filter(function () {return _.str.include($(this).text(), '0.00');});
- assert.strictEqual(zeroValues.length, 2,
- 'Unset float values should be rendered as zeros.');
+ var zeroValues = list.$('td.o_data_cell').filter(function () {return $(this).text() === '';});
+ assert.strictEqual(zeroValues.length, 1,
+ 'Unset float values should be rendered as empty strings.');
// switch to edit mode
var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector):contains($)');
@@ -1736,6 +1742,67 @@ QUnit.module('basic_fields', {
form.destroy();
});
+ QUnit.test('should keep the focus when being edited in x2many lists', function (assert) {
+ assert.expect(6);
+
+ this.data.partner.fields.currency_id.default = 1;
+ this.data.partner.fields.m2m = {
+ string: "m2m", type: "many2many", relation: 'partner', default: [[6, false, [2]]],
+ };
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch:'<form string="Partners">' +
+ '<sheet>' +
+ '<field name="p"/>' +
+ '<field name="m2m"/>' +
+ '</sheet>' +
+ '</form>',
+ archs: {
+ 'partner,false,list': '<tree editable="bottom">' +
+ '<field name="qux" widget="monetary"/>' +
+ '<field name="currency_id" invisible="1"/>' +
+ '</tree>',
+ },
+ session: {
+ currencies: _.indexBy(this.data.currency.records, 'id'),
+ },
+ });
+
+ // test the monetary field inside the one2many
+ var $o2m = form.$('.o_field_widget[name=p]');
+ $o2m.find('.o_field_x2many_list_row_add a').click();
+ $o2m.find('.o_field_widget input').val("22").trigger('input');
+
+ assert.strictEqual($o2m.find('.o_field_widget input').get(0), document.activeElement,
+ "the focus should still be on the input");
+ assert.strictEqual($o2m.find('.o_field_widget input').val(), "22",
+ "the value should not have been formatted yet");
+
+ form.$el.click(); // focusout the input
+
+ assert.strictEqual($o2m.find('.o_field_widget[name=qux]').html(), "$&nbsp;22.00",
+ "the value should have been formatted after losing the focus");
+
+ // test the monetary field inside the many2many
+ var $m2m = form.$('.o_field_widget[name=m2m]');
+ $m2m.find('.o_data_row td:first').click();
+ $m2m.find('.o_field_widget input').val("22").trigger('input');
+
+ assert.strictEqual($m2m.find('.o_field_widget input').get(0), document.activeElement,
+ "the focus should still be on the input");
+ assert.strictEqual($m2m.find('.o_field_widget input').val(), "22",
+ "the value should not have been formatted yet");
+
+ form.$el.click(); // focusout the input
+
+ assert.strictEqual($m2m.find('.o_field_widget[name=qux]').html(), "22.00&nbsp;€",
+ "the value should have been formatted after losing the focus");
+
+ form.destroy();
+ });
+
QUnit.module('FieldInteger');
QUnit.test('integer field when unset', function (assert) {
diff --git a/addons/web/static/tests/fields/field_utils_tests.js b/addons/web/static/tests/fields/field_utils_tests.js
index d56f077b828..bfd60000035 100644
--- a/addons/web/static/tests/fields/field_utils_tests.js
+++ b/addons/web/static/tests/fields/field_utils_tests.js
@@ -23,13 +23,13 @@ QUnit.test('format integer', function(assert) {
assert.strictEqual(fieldUtils.format.integer(106500), '106,50,0');
assert.strictEqual(fieldUtils.format.integer(0), "0");
- assert.strictEqual(fieldUtils.format.integer(undefined), "");
+ assert.strictEqual(fieldUtils.format.integer(false), "");
core._t.database.parameters.grouping = originalGrouping;
});
QUnit.test('format float', function(assert) {
- assert.expect(4);
+ assert.expect(5);
var originalParameters = $.extend(true, {}, core._t.database.parameters);
@@ -48,6 +48,7 @@ QUnit.test('format float', function(assert) {
thousands_sep: '.'
});
assert.strictEqual(fieldUtils.format.float(6000), '6.000,00');
+ assert.strictEqual(fieldUtils.format.float(false), '');
core._t.database.parameters = originalParameters;
});
@@ -70,6 +71,12 @@ QUnit.test("format_many2one", function (assert) {
}));
});
+QUnit.test('format monetary', function(assert) {
+ assert.expect(1);
+
+ assert.strictEqual(fieldUtils.format.monetary(false), '');
+});
+
QUnit.test('format char', function(assert) {
assert.expect(1);
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index fc613fc6d45..44b41219d52 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -142,7 +142,7 @@ QUnit.module('relational_fields', {
QUnit.module('FieldMany2One');
QUnit.test('many2ones in form views', function (assert) {
- assert.expect(4);
+ assert.expect(5);
var form = createView({
View: FormView,
model: 'partner',
@@ -150,10 +150,13 @@ QUnit.module('relational_fields', {
arch: '<form string="Partners">' +
'<sheet>' +
'<group>' +
- '<field name="trululu"/>' +
+ '<field name="trululu" string="custom label"/>' +
'</group>' +
'</sheet>' +
'</form>',
+ archs: {
+ 'partner,false,form': '<form string="Partners"><field name="display_name"/></form>',
+ },
res_id: 1,
mockRPC: function (route, args) {
if (args.method === 'get_formview_action') {
@@ -177,11 +180,6 @@ QUnit.module('relational_fields', {
assert.strictEqual(event.data.action.res_id, 17,
"should do a do_action with correct parameters");
});
- testUtils.intercept(form, 'load_views', function (event) {
- // temporarily prevent the fields_view from being loaded (to prevent a crash)
- // TODO: specify a fields_view and test that we can edit the record in the dialog
- event.stopPropagation();
- });
assert.strictEqual(form.$('a.o_form_uri:contains(aaa)').length, 1,
"should contain a link");
@@ -191,6 +189,9 @@ QUnit.module('relational_fields', {
form.$('.o_external_button').click(); // click on the external button (should do an RPC)
+ assert.strictEqual($('.modal .modal-title').text().trim(), 'Open: custom label',
+ "dialog title should display the custom string label");
+
// TODO: test that we can edit the record in the dialog, and that the value is correctly
// updated on close
form.destroy();
@@ -2185,7 +2186,7 @@ QUnit.module('relational_fields', {
});
QUnit.test('one2many with many2many widget: edition', function (assert) {
- assert.expect(6);
+ assert.expect(7);
var form = createView({
View: FormView,
@@ -2230,6 +2231,8 @@ QUnit.module('relational_fields', {
});
form.$('.o_data_row:first').click();
+ assert.strictEqual($('.modal .modal-title').first().text().trim(), 'Open: one2many turtle field',
+ "modal should use the python field string as title");
$('.modal .o_form_button_cancel').click();
form.$buttons.find('.o_form_button_edit').click();
diff --git a/addons/web/static/tests/helpers/mock_server.js b/addons/web/static/tests/helpers/mock_server.js
index 60024292edd..e7ee9bf07d2 100644
--- a/addons/web/static/tests/helpers/mock_server.js
+++ b/addons/web/static/tests/helpers/mock_server.js
@@ -62,6 +62,9 @@ var MockServer = Class.extend({
* @returns {Object} an object with 2 keys: arch and fields
*/
fieldsViewGet: function (arch, model, toolbar) {
+ if (!(model in this.data)) {
+ throw new Error('Model ' + model + ' was not defined in mock server data');
+ }
var fields = $.extend(true, {}, this.data[model].fields);
var fvg = this._fieldsViewGet(arch, model, fields);
var fields_views = {};
@@ -768,6 +771,8 @@ var MockServer = Class.extend({
return result;
});
if (args.sort) {
+ // deal with sort on multiple fields (i.e. only consider the first)
+ args.sort = args.sort.split(',')[0];
var fieldName = args.sort.split(' ')[0];
var order = args.sort.split(' ')[1];
processedRecords.sort(function (r1, r2) {
@@ -898,7 +903,7 @@ var MockServer = Class.extend({
}
var model = this.data[args.model];
if (model && typeof model[args.method] === 'function') {
- return this.data[args.model][args.method](args.args, args.kwargs);
+ return $.when(this.data[args.model][args.method](args.args, args.kwargs));
}
console.error("Unimplemented route", route, args);
diff --git a/addons/web/static/tests/helpers/qunit_config.js b/addons/web/static/tests/helpers/qunit_config.js
index c161fc95d23..641d3a6f09b 100644
--- a/addons/web/static/tests/helpers/qunit_config.js
+++ b/addons/web/static/tests/helpers/qunit_config.js
@@ -36,7 +36,7 @@ QUnit.config.testTimeout = 1 * 60 * 1000;
/**
* Hide passed tests by default in the QUnit page
*/
-QUnit.config.hidepassed = true;
+QUnit.config.hidepassed = (window.location.href.match(/[?&]testId=/) === null);
var sortButtonAppended = false;
@@ -62,11 +62,18 @@ QUnit.done(function(result) {
* This logs various data in the console, which will be available in the log
* .txt file generated by the runbot.
*/
-QUnit.log(function( result) {
+QUnit.log(function (result) {
if (!result.result) {
- console.log('"' + result.name + '"',
- 'in section', '"' + result.module + '"',
- 'failed:', result.message);
+ var info = '"QUnit test failed: "' + result.module + ' > ' + result.name + '"';
+ info += ' [message: "' + result.message + '"';
+ if (result.actual !== null) {
+ info += ', actual: "' + result.actual + '"';
+ }
+ if (result.expected !== null) {
+ info += ', expected: "' + result.expected + '"';
+ }
+ info += ']';
+ console.error(info);
}
});
diff --git a/addons/web/static/tests/helpers/test_utils.js b/addons/web/static/tests/helpers/test_utils.js
index 516971f96fe..9f46ce6f2e3 100644
--- a/addons/web/static/tests/helpers/test_utils.js
+++ b/addons/web/static/tests/helpers/test_utils.js
@@ -23,21 +23,23 @@ var DebouncedField = basic_fields.DebouncedField;
* intercepts an event bubbling up the widget hierarchy. The event intercepted
* must be a "custom event", i.e. an event generated by the method 'trigger_up'.
*
- * Note that this method really intercepts the event. It will not be propagated
- * further, and even the handlers on the target will not fire.
+ * Note that this method really intercepts the event if @propagate is not set.
+ * It will not be propagated further, and even the handlers on the target will
+ * not fire.
*
* @param {Widget} widget the target widget (any Odoo widget)
* @param {string} eventName description of the event
* @param {function} fn callback executed when the even is intercepted
+ * @param {boolean} [propagate=false]
*/
-function intercept(widget, eventName, fn) {
+function intercept(widget, eventName, fn, propagate) {
var _trigger_up = widget._trigger_up.bind(widget);
widget._trigger_up = function (event) {
if (event.name === eventName) {
fn(event);
- } else {
- _trigger_up(event);
+ if (!propagate) { return; }
}
+ _trigger_up(event);
};
}
@@ -143,7 +145,7 @@ function createAsyncView(params) {
var view = new params.View(viewInfo, viewOptions);
// make sure images do not trigger a GET on the server
- $('#qunit-fixture').on('DOMNodeInserted.removeSRC', function () {
+ $target.on('DOMNodeInserted.removeSRC', function () {
removeSrcAttribute($(this), widget);
});
@@ -436,9 +438,15 @@ function triggerPositionalMouseEvent(x, y, type){
*/
function removeSrcAttribute($el, widget) {
$el.find('img, iframe[src]').each(function () {
- var src = $(this).attr('src');
- if (src[0] !== '#') {
- $(this).attr('src', '#test:' + $(this).attr('src'));
+ var $el = $(this);
+ var src = $el.attr('src');
+ if (src[0] !== '#' && src !== 'about:blank') {
+ if ($el[0].nodeName === 'IMG') {
+ $el.attr('src', '#test:' + src);
+ } else {
+ $el.attr('data-src', src);
+ $el.attr('src', 'about:blank');
+ }
if (widget) {
widget._rpc({route: src});
}
diff --git a/addons/web/static/tests/views/basic_model_tests.js b/addons/web/static/tests/views/basic_model_tests.js
index 5f4f94352df..180d38668c7 100644
--- a/addons/web/static/tests/views/basic_model_tests.js
+++ b/addons/web/static/tests/views/basic_model_tests.js
@@ -1331,4 +1331,44 @@ QUnit.module('Views', {
"there should be only one read");
model.destroy();
});
+
+ QUnit.test('data should contain all fields in view, default being false', function (assert) {
+ assert.expect(1);
+
+ this.data.partner.fields.product_ids.default = [
+ [6, 0, []],
+ [0, 0, {name: 'new'}],
+ ];
+ this.data.product.fields.date = { string: "Date", type: "date" };
+
+ var params = {
+ fieldNames: ['product_ids'],
+ modelName: 'partner',
+ fields: this.data.partner.fields,
+ fieldsInfo: {
+ form: {
+ product_ids: {
+ fieldsInfo: { list: { name: {}, date: {} } },
+ viewType: 'list',
+ }
+ },
+ },
+ res_id: undefined,
+ type: 'record',
+ viewType: 'form',
+ };
+
+ var model = createModel({
+ Model: BasicModel,
+ data: this.data,
+ });
+
+ model.load(params).then(function (resultID) {
+ var record = model.get(resultID);
+ assert.strictEqual(record.data.product_ids.data[0].data.date, false,
+ "date value should be in data, and should be false");
+ });
+
+ model.destroy();
+ });
});});
diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js
index 7010771e992..b81c1965b32 100644
--- a/addons/web/static/tests/views/calendar_tests.js
+++ b/addons/web/static/tests/views/calendar_tests.js
@@ -396,7 +396,14 @@ QUnit.module('Views', {
var top = calendar.$('.fc-axis:contains(8am)').offset().top + 5;
var left = calendar.$('.fc-day:eq(2)').offset().left + 5;
- testUtils.triggerPositionalMouseEvent(left, top, "mousedown");
+ try {
+ testUtils.triggerPositionalMouseEvent(left, top, "mousedown");
+ } catch (e) {
+ calendar.destroy();
+ $view.remove();
+ throw new Error('The test fails to simulate a click in the screen. Your screen is probably too small or your dev tools is open.');
+ }
+
testUtils.triggerPositionalMouseEvent(left, top + 60, "mousemove");
assert.strictEqual(calendar.$('.fc-content .fc-time').text(), "08:00 - 10:00",
@@ -497,7 +504,13 @@ QUnit.module('Views', {
var top = calendar.$('.fc-axis:contains(8am)').offset().top + 5;
var left = calendar.$('.fc-day:eq(2)').offset().left + 5;
- testUtils.triggerPositionalMouseEvent(left, top, "mousedown");
+ try {
+ testUtils.triggerPositionalMouseEvent(left, top, "mousedown");
+ } catch (e) {
+ calendar.destroy();
+ $view.remove();
+ throw new Error('The test fails to simulate a click in the screen. Your screen is probably too small or your dev tools is open.');
+ }
testUtils.triggerPositionalMouseEvent(left, top + 60, "mousemove");
testUtils.triggerPositionalMouseEvent(left, top + 60, "mouseup");
$('.modal input:first').val('new event').trigger('input');
@@ -593,7 +606,13 @@ QUnit.module('Views', {
var pos = calendar.$('.fc-bg td:eq(4)').offset();
- testUtils.triggerPositionalMouseEvent(pos.left+15, pos.top+15, "mousedown");
+ try {
+ testUtils.triggerPositionalMouseEvent(pos.left+15, pos.top+15, "mousedown");
+ } catch (e) {
+ calendar.destroy();
+ $view.remove();
+ throw new Error('The test fails to simulate a click in the screen. Your screen is probably too small or your dev tools is open.');
+ }
pos = calendar.$('.fc-bg td:eq(5)').offset();
testUtils.triggerPositionalMouseEvent(pos.left+15, pos.top+15, "mousemove");
testUtils.triggerPositionalMouseEvent(pos.left+15, pos.top+15, "mouseup");
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index bedcf83b139..7afb8545934 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -576,6 +576,53 @@ QUnit.module('Views', {
form.destroy();
});
+ QUnit.test('empty fields\' labels still get the empty class after widget rerender', function (assert) {
+ assert.expect(6);
+
+ this.data.partner.fields.foo.default = false; // no default value for this test
+ this.data.partner.records[1].foo = false; // 1 is record with id=2
+ this.data.partner.records[1].int_field = false; // 1 is record with id=2
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form>' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="foo"/>' +
+ '<field name="int_field" attrs="{\'readonly\': [[\'foo\', \'=\', \'readonly\']]}"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 2,
+ });
+
+ assert.strictEqual(form.$('.o_field_widget.o_field_empty').length, 2,
+ "should have 2 empty fields with correct class");
+ assert.strictEqual(form.$('.o_form_label_empty').length, 2,
+ "should have 2 muted labels (for the empty fieds) in readonly");
+
+ form.$buttons.find('.o_form_button_edit').click();
+
+ assert.strictEqual(form.$('.o_field_empty').length, 0,
+ "in edit mode, only empty readonly fields should have the o_field_empty class");
+ assert.strictEqual(form.$('.o_form_label_empty').length, 0,
+ "in edit mode, only labels associated to empty readonly fields should have the o_form_label_empty class");
+
+ form.$('input[name="foo"]').val("readonly").trigger("input"); // int_field is now rerendered as readonly
+ form.$('input[name="foo"]').val("edit").trigger("input"); // int_field is now rerendered as editable
+ form.$('input[name="int_field"]').val('1').trigger("input"); // int_field is now set
+ form.$('input[name="foo"]').val("readonly").trigger("input"); // int_field is now rerendered as readonly
+
+ assert.strictEqual(form.$('.o_field_empty').length, 0,
+ "there still should not be any empty class on fields as the readonly one is now set");
+ assert.strictEqual(form.$('.o_form_label_empty').length, 0,
+ "there still should not be any empty class on labels as the associated readonly field is now set");
+
+ form.destroy();
+ });
+
QUnit.test('empty inner readonly fields don\'t have o_form_empty class in "create" mode', function (assert) {
assert.expect(2);
@@ -696,6 +743,50 @@ QUnit.module('Views', {
form.destroy();
});
+ QUnit.test('required float fields works as expected', function (assert) {
+ assert.expect(8);
+
+ this.data.partner.fields.qux.required = true;
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="qux"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ mockRPC: function (route, args) {
+ assert.step(args.method);
+ return this._super.apply(this, arguments);
+ },
+ });
+
+ assert.ok(form.$('input[name="qux"]').hasClass('o_required_modifier'),
+ "qux input is flagged as required");
+ assert.strictEqual(form.$('input[name="qux"]').val(), "",
+ "qux input is empty");
+
+ form.$buttons.find('.o_form_button_save').click();
+
+ assert.ok(form.$('input[name="qux"]').hasClass('o_field_invalid'),
+ "qux input is displayed as invalid");
+
+ form.$('input[name="qux"]').val("0").trigger('input');
+
+ form.$buttons.find('.o_form_button_save').click();
+
+ form.$buttons.find('.o_form_button_edit').click();
+
+ assert.strictEqual(form.$('input[name="qux"]').val(), "0.0",
+ "qux input is properly formatted");
+
+ assert.verifySteps(['default_get', 'create', 'read']);
+ form.destroy();
+ });
+
QUnit.test('separators', function (assert) {
assert.expect(1);
@@ -1082,7 +1173,7 @@ QUnit.module('Views', {
'</form>',
viewOptions: {sidebar: true},
res_id: 1,
- mockRPC: function(route, args) {
+ mockRPC: function (route, args) {
if (args.method === 'search_read' && args.model === 'ir.attachment') {
return $.when([]);
}
@@ -1227,7 +1318,7 @@ QUnit.module('Views', {
'</form>',
res_id: 1,
viewOptions: {sidebar: true},
- mockRPC: function(route, args) {
+ mockRPC: function (route, args) {
if (args.method === 'search_read' && args.model === 'ir.attachment') {
return $.when([]);
}
@@ -1410,8 +1501,8 @@ QUnit.module('Views', {
assert.strictEqual(form.$("label").eq(1).text(), "Bar",
"one should be the one for the bar field");
- assert.strictEqual(form.$('.firstgroup td').first().attr('colspan'), "1",
- "foo td should have a colspan of 1");
+ assert.strictEqual(form.$('.firstgroup td').first().attr('colspan'), undefined,
+ "foo td should have a default colspan (1)");
assert.strictEqual(form.$('.secondgroup tr').length, 2,
"int_field and qux should have same tr");
@@ -1678,7 +1769,7 @@ QUnit.module('Views', {
arch: '<form string="Partners"><field name="foo"></field></form>',
res_id: 1,
viewOptions: {sidebar: true},
- mockRPC: function(route, args) {
+ mockRPC: function (route, args) {
if (args.method === 'search_read' && args.model === 'ir.attachment') {
return $.when([]);
}
@@ -2025,7 +2116,7 @@ QUnit.module('Views', {
sidebar: true,
},
res_id: 1,
- mockRPC: function(route, args) {
+ mockRPC: function (route, args) {
if (args.method === 'search_read' && args.model === 'ir.attachment') {
return $.when([]);
}
@@ -2839,7 +2930,7 @@ QUnit.module('Views', {
});
QUnit.test('onchange value are not discarded on o2m edition', function (assert) {
- assert.expect(3);
+ assert.expect(4);
this.data.partner.records[1].p = [4];
this.data.partner.onchanges = {
@@ -2894,6 +2985,8 @@ QUnit.module('Views', {
"onchange should have been correctly applied on field in o2m list");
form.$('.o_data_row').click(); // edit the o2m in the dialog
+ assert.strictEqual($('.modal .modal-title').text().trim(), 'Open: one2many field',
+ "the field string is displayed in the modal title");
assert.strictEqual($('.modal .o_field_widget').val(), 'foo changed',
"the onchange value hasn't been discarded when opening the o2m");
@@ -2949,7 +3042,7 @@ QUnit.module('Views', {
});
QUnit.test('args of onchanges in o2m fields are correct (dialog edition)', function (assert) {
- assert.expect(5);
+ assert.expect(6);
this.data.partner.records[1].p = [4];
this.data.partner.fields.p.relation_field = 'rel_field';
@@ -2966,7 +3059,7 @@ QUnit.module('Views', {
arch: '<form>' +
'<group>' +
'<field name="foo"/>' +
- '<field name="p">' +
+ '<field name="p" string="custom label">' +
'<tree>' +
'<field name="foo"/>' +
'</tree>' +
@@ -2995,6 +3088,8 @@ QUnit.module('Views', {
// create a new o2m record
form.$('.o_field_x2many_list_row_add a').click();
+ assert.strictEqual($('.modal .modal-title').text().trim(), 'Create custom label',
+ "the custom field label is applied in the modal title");
assert.strictEqual($('.modal input:first').val(), '[blip] 14',
"onchange should have been correctly applied after default get");
$('.modal .modal-footer .btn-primary').click(); // save the dialog
@@ -3433,6 +3528,34 @@ QUnit.module('Views', {
}
});
+ QUnit.test('footers are not duplicated on rerender', function (assert) {
+ assert.expect(2);
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch:
+ '<form>' +
+ '<field name="foo"/>' +
+ '<footer>' +
+ '<button>Hello</button>' +
+ '</footer>' +
+ '</form>',
+ res_id: 1,
+ viewOptions: {
+ footer_to_buttons: true,
+ },
+ });
+
+ assert.strictEqual(form.$('footer').length, 0,
+ "footer should have been moved outside of the form view");
+ form.reload();
+ assert.strictEqual(form.$('footer').length, 0,
+ "footer should still have been moved outside of the form view");
+ form.destroy();
+ });
+
QUnit.test('render stat button with string inline', function (assert) {
assert.expect(1);
@@ -3652,49 +3775,49 @@ QUnit.module('Views', {
});
QUnit.test('onchanges are applied before checking if it can be saved', function (assert) {
- assert.expect(4);
-
- this.data.partner.onchanges.foo = function (obj) {};
- this.data.partner.fields.foo.required = true;
-
- var def = $.Deferred();
-
- var form = createView({
- View: FormView,
- model: 'partner',
- data: this.data,
- arch: '<form string="Partners">' +
- '<sheet><group>' +
- '<field name="foo"/>' +
- '</group></sheet>' +
- '</form>',
- res_id: 2,
- mockRPC: function (route, args) {
- var result = this._super.apply(this, arguments);
- assert.step(args.method);
- if (args.method === 'onchange') {
- return def.then(function () {
- return result;
- });
- }
- return result;
- },
- intercepts: {
- warning: function () {
- assert.step('warning');
- },
- },
- });
-
- form.$buttons.find('.o_form_button_edit').click();
- form.$('input[name="foo"]').val('').trigger("input");
- form.$buttons.find('.o_form_button_save').click();
-
- def.resolve();
-
- assert.verifySteps(['read', 'onchange', 'warning'])
- form.destroy();
- });
+ assert.expect(4);
+
+ this.data.partner.onchanges.foo = function (obj) {};
+ this.data.partner.fields.foo.required = true;
+
+ var def = $.Deferred();
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<sheet><group>' +
+ '<field name="foo"/>' +
+ '</group></sheet>' +
+ '</form>',
+ res_id: 2,
+ mockRPC: function (route, args) {
+ var result = this._super.apply(this, arguments);
+ assert.step(args.method);
+ if (args.method === 'onchange') {
+ return def.then(function () {
+ return result;
+ });
+ }
+ return result;
+ },
+ intercepts: {
+ warning: function () {
+ assert.step('warning');
+ },
+ },
+ });
+
+ form.$buttons.find('.o_form_button_edit').click();
+ form.$('input[name="foo"]').val('').trigger("input");
+ form.$buttons.find('.o_form_button_save').click();
+
+ def.resolve();
+
+ assert.verifySteps(['read', 'onchange', 'warning']);
+ form.destroy();
+ });
QUnit.test('display toolbar', function (assert) {
assert.expect(7);
@@ -3719,7 +3842,7 @@ QUnit.module('Views', {
viewOptions: {
sidebar: true,
},
- mockRPC: function(route, args) {
+ mockRPC: function (route, args) {
if (route === '/web/action/load') {
assert.strictEqual(args.context.active_id, 1,
"the active_id shoud be 1.");
@@ -3764,7 +3887,7 @@ QUnit.module('Views', {
});
QUnit.test('check interactions between multiple FormViewDialogs', function (assert) {
- assert.expect(7);
+ assert.expect(8);
this.data.product.fields.product_ids = {
string: "one2many product", type: "one2many", relation: "product",
@@ -3815,6 +3938,8 @@ QUnit.module('Views', {
assert.strictEqual($('.modal').length, 1,
"One FormViewDialog should be opened");
var $firstModal = $('.modal');
+ assert.strictEqual($('.modal .modal-title').first().text().trim(), 'Open: Product',
+ "dialog title should display the python field string as label");
assert.strictEqual($firstModal.find('input').val(), 'xphone',
"display_name should be correctly displayed");
@@ -4054,5 +4179,249 @@ QUnit.module('Views', {
form.destroy();
});
+
+ QUnit.test('form rendering with groups with col/colspan', function (assert) {
+ assert.expect(46);
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch:
+ '<form>' +
+ '<sheet>' +
+ '<group col="6" class="parent_group">' +
+ '<group col="4" colspan="3" class="group_4">' +
+ '<div colspan="3"/>' +
+ '<div colspan="2"/><div/>' +
+ '<div colspan="4"/>' +
+ '</group>' +
+ '<group col="3" colspan="4" class="group_3">' +
+ '<group col="1" class="group_1">' +
+ '<div/><div/><div/>' +
+ '</group>' +
+ '<div/>' +
+ '<group col="3" class="field_group">' +
+ '<field name="foo" colspan="3"/>' +
+ '<div/><field name="bar" nolabel="1"/>' +
+ '<field name="qux"/>' +
+ '<field name="int_field" colspan="3" nolabel="1"/>' +
+ '<span/><field name="product_id"/>' +
+ '</group>' +
+ '</group>' +
+ '</group>' +
+ '<group>' +
+ '<field name="p">' +
+ '<tree>' +
+ '<field name="display_name"/>' +
+ '<field name="foo"/>' +
+ '<field name="int_field"/>' +
+ '</tree>' +
+ '</field>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ });
+
+ var $parentGroup = form.$('.parent_group');
+ var $group4 = form.$('.group_4');
+ var $group3 = form.$('.group_3');
+ var $group1 = form.$('.group_1');
+ var $fieldGroup = form.$('.field_group');
+
+ // Verify outergroup/innergroup
+ assert.strictEqual($parentGroup[0].tagName, 'DIV', ".parent_group should be an outergroup");
+ assert.strictEqual($group4[0].tagName, 'TABLE', ".group_4 should be an innergroup");
+ assert.strictEqual($group3[0].tagName, 'DIV', ".group_3 should be an outergroup");
+ assert.strictEqual($group1[0].tagName, 'TABLE', ".group_1 should be an innergroup");
+ assert.strictEqual($fieldGroup[0].tagName, 'TABLE', ".field_group should be an innergroup");
+
+ // Verify .parent_group content
+ var $parentGroupChildren = $parentGroup.children();
+ assert.strictEqual($parentGroupChildren.length, 2, "there should be 2 groups in .parent_group");
+ assert.ok($parentGroupChildren.eq(0).is('.o_group_col_6'), "first .parent_group group should be 1/2 parent width");
+ assert.ok($parentGroupChildren.eq(1).is('.o_group_col_8'), "second .parent_group group should be 2/3 parent width");
+
+ // Verify .group_4 content
+ var $group4rows = $group4.find('> tbody > tr');
+ assert.strictEqual($group4rows.length, 3, "there should be 3 rows in .group_4");
+ var $group4firstRowTd = $group4rows.eq(0).children('td');
+ assert.strictEqual($group4firstRowTd.length, 1, "there should be 1 td in first row");
+ assert.strictEqual($group4firstRowTd.attr('colspan'), "3", "the first td colspan should be 3");
+ assert.strictEqual($group4firstRowTd.attr('style').substr(0, 9), "width: 75", "the first td should be 75% width");
+ assert.strictEqual($group4firstRowTd.children()[0].tagName, "DIV", "the first td should contain a div");
+ var $group4secondRowTds = $group4rows.eq(1).children('td');
+ assert.strictEqual($group4secondRowTds.length, 2, "there should be 2 tds in second row");
+ assert.strictEqual($group4secondRowTds.eq(0).attr('colspan'), "2", "the first td colspan should be 2");
+ assert.strictEqual($group4secondRowTds.eq(0).attr('style').substr(0, 9), "width: 50", "the first td be 50% width");
+ assert.strictEqual($group4secondRowTds.eq(1).attr('colspan'), undefined, "the second td colspan should be default one (1)");
+ assert.strictEqual($group4secondRowTds.eq(1).attr('style').substr(0, 9), "width: 25", "the second td be 75% width");
+ var $group4thirdRowTd = $group4rows.eq(2).children('td');
+ assert.strictEqual($group4thirdRowTd.length, 1, "there should be 1 td in third row");
+ assert.strictEqual($group4thirdRowTd.attr('colspan'), "4", "the first td colspan should be 4");
+ assert.strictEqual($group4thirdRowTd.attr('style').substr(0, 10), "width: 100", "the first td should be 100% width");
+
+ // Verify .group_3 content
+ assert.strictEqual($group3.children().length, 3, ".group_3 should have 3 children");
+ assert.strictEqual($group3.children('.o_group_col_4').length, 3, ".group_3 should have 3 children of 1/3 width");
+
+ // Verify .group_1 content
+ assert.strictEqual($group1.find('> tbody > tr').length, 3, "there should be 3 rows in .group_1");
+
+ // Verify .field_group content
+ var $fieldGroupRows = $fieldGroup.find('> tbody > tr');
+ assert.strictEqual($fieldGroupRows.length, 5, "there should be 5 rows in .field_group");
+ var $fieldGroupFirstRowTds = $fieldGroupRows.eq(0).children('td');
+ assert.strictEqual($fieldGroupFirstRowTds.length, 2, "there should be 2 tds in first row");
+ assert.ok($fieldGroupFirstRowTds.eq(0).hasClass('o_td_label'), "first td should be a label td");
+ assert.strictEqual($fieldGroupFirstRowTds.eq(1).attr('colspan'), "2", "second td colspan should be given colspan (3) - 1 (label)");
+ assert.strictEqual($fieldGroupFirstRowTds.eq(1).attr('style').substr(0, 10), "width: 100", "second td width should be 100%");
+ var $fieldGroupSecondRowTds = $fieldGroupRows.eq(1).children('td');
+ assert.strictEqual($fieldGroupSecondRowTds.length, 2, "there should be 2 tds in second row");
+ assert.strictEqual($fieldGroupSecondRowTds.eq(0).attr('colspan'), undefined, "first td colspan should be default one (1)");
+ assert.strictEqual($fieldGroupSecondRowTds.eq(0).attr('style').substr(0, 9), "width: 33", "first td width should be 33.3333%");
+ assert.strictEqual($fieldGroupSecondRowTds.eq(1).attr('colspan'), undefined, "second td colspan should be default one (1)");
+ assert.strictEqual($fieldGroupSecondRowTds.eq(1).attr('style').substr(0, 9), "width: 33", "second td width should be 33.3333%");
+ var $fieldGroupThirdRowTds = $fieldGroupRows.eq(2).children('td'); // new row as label/field pair colspan is greater than remaining space
+ assert.strictEqual($fieldGroupThirdRowTds.length, 2, "there should be 2 tds in third row");
+ assert.ok($fieldGroupThirdRowTds.eq(0).hasClass('o_td_label'), "first td should be a label td");
+ assert.strictEqual($fieldGroupThirdRowTds.eq(1).attr('colspan'), undefined, "second td colspan should be default one (1)");
+ assert.strictEqual($fieldGroupThirdRowTds.eq(1).attr('style').substr(0, 9), "width: 50", "second td should be 50% width");
+ var $fieldGroupFourthRowTds = $fieldGroupRows.eq(3).children('td');
+ assert.strictEqual($fieldGroupFourthRowTds.length, 1, "there should be 1 td in fourth row");
+ assert.strictEqual($fieldGroupFourthRowTds.attr('colspan'), "3", "the td should have a colspan equal to 3");
+ assert.strictEqual($fieldGroupFourthRowTds.attr('style').substr(0, 10), "width: 100", "the td should have 100% width");
+ var $fieldGroupFifthRowTds = $fieldGroupRows.eq(4).children('td'); // label/field pair can be put after the 1-colspan span
+ assert.strictEqual($fieldGroupFifthRowTds.length, 3, "there should be 3 tds in fourth row");
+ assert.strictEqual($fieldGroupFifthRowTds.eq(0).attr('style').substr(0, 9), "width: 50", "the first td should 50% width");
+ assert.ok($fieldGroupFifthRowTds.eq(1).hasClass('o_td_label'), "the second td should be a label td");
+ assert.strictEqual($fieldGroupFifthRowTds.eq(2).attr('style').substr(0, 9), "width: 50", "the third td should 50% width");
+
+ // Verify that one2many list table hasn't been impacted
+ assert.strictEqual(form.$('.o_field_one2many th:first').attr('style'), undefined,
+ "o2m list columns should have no width harcoded");
+
+ form.destroy();
+ });
+
+ QUnit.test('form group with newline tag inside', function (assert) {
+ assert.expect(6);
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch:
+ '<form>' +
+ '<sheet>' +
+ '<group col="5" class="main_inner_group">' +
+ // col=5 otherwise the test is ok even without the
+ // newline code as this will render a <newline/> DOM
+ // element in the third column, leaving no place for
+ // the next field and its label on the same line.
+ '<field name="foo"/>' +
+ '<newline/>' +
+ '<field name="bar"/>' +
+ '<field name="qux"/>' +
+ '</group>' +
+ '<group col="3">' +
+ // col=3 otherwise the test is ok even without the
+ // newline code as this will render a <newline/> DOM
+ // element with the o_group_col_6 class, leaving no
+ // place for the next group on the same line.
+ '<group class="top_group">' +
+ '<div style="height: 200px;"/>' +
+ '</group>' +
+ '<newline/>' +
+ '<group class="bottom_group">' +
+ '<div/>' +
+ '</group>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ });
+
+ // Inner group
+ assert.strictEqual(form.$('.main_inner_group > tbody > tr').length, 2,
+ "there should be 2 rows in the group");
+ assert.strictEqual(form.$('.main_inner_group > tbody > tr:first > .o_td_label').length, 1,
+ "there should be only one label in the first row");
+ assert.strictEqual(form.$('.main_inner_group > tbody > tr:first .o_field_widget').length, 1,
+ "there should be only one widget in the first row");
+ assert.strictEqual(form.$('.main_inner_group > tbody > tr:last > .o_td_label').length, 2,
+ "there should be two labels in the second row");
+ assert.strictEqual(form.$('.main_inner_group > tbody > tr:last .o_field_widget').length, 2,
+ "there should be two widgets in the second row");
+
+ // Outer group
+ assert.ok((form.$('.bottom_group').position().top - form.$('.top_group').position().top) >= 200,
+ "outergroup children should not be on the same line");
+
+ form.destroy();
+ });
+
+ QUnit.test('custom open record dialog title', function (assert) {
+ assert.expect(1);
+
+ this.data.partner.records[0].p = [2];
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch:'<form string="Partners">' +
+ '<field name="p" widget="many2many" string="custom label">' +
+ '<tree>' +
+ '<field name="display_name"/>' +
+ '</tree>' +
+ '<form>' +
+ '<field name="display_name"/>' +
+ '</form>' +
+ '</field>' +
+ '</form>',
+ session: {},
+ res_id: 1,
+ });
+
+ form.$('.o_data_row:first').click();
+ assert.strictEqual($('.modal .modal-title').first().text().trim(), 'Open: custom label',
+ "modal should use the python field string as title");
+
+ form.destroy();
+ });
+
+ QUnit.test('display translation alert', function (assert) {
+ assert.expect(1);
+
+ this.data.partner.fields.foo.translate = true;
+
+ var multi_lang = _t.database.multi_lang;
+ _t.database.multi_lang = true;
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="foo"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ });
+
+ form.$buttons.find('.o_form_button_edit').click();
+ form.$('input[name="foo"]').val("test").trigger("input");
+ form.$buttons.find('.o_form_button_save').click();
+
+ assert.strictEqual(form.$('.o_form_view > .alert > div').length, 1,"should have a translation alert");
+
+ form.destroy();
+
+ _t.database.multi_lang = multi_lang;
+ });
});
});
diff --git a/addons/web/static/tests/views/kanban_benchmarks.js b/addons/web/static/tests/views/kanban_benchmarks.js
new file mode 100644
index 00000000000..d0df270089f
--- /dev/null
+++ b/addons/web/static/tests/views/kanban_benchmarks.js
@@ -0,0 +1,83 @@
+odoo.define('web.kanban_benchmarks', function (require) {
+"use strict";
+
+var KanbanView = require('web.KanbanView');
+var testUtils = require('web.test_utils');
+
+var createView = testUtils.createView;
+
+QUnit.module('Kanban View', {
+ beforeEach: function () {
+ this.data = {
+ foo: {
+ fields: {
+ foo: {string: "Foo", type: "char"},
+ bar: {string: "Bar", type: "boolean"},
+ int_field: {string: "int_field", type: "integer", sortable: true},
+ qux: {string: "my float", type: "float"},
+ },
+ records: [
+ { id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4},
+ {id: 2, bar: true, foo: "blip", int_field: 9, qux: 13},
+ ]
+ },
+ };
+ this.arch = null;
+ this.run = function (assert, done) {
+ var data = this.data;
+ var arch = this.arch;
+ new Benchmark.Suite({})
+ .add('kanban', function () {
+ var kanban = createView({
+ View: KanbanView,
+ model: 'foo',
+ data: data,
+ arch: arch,
+ });
+ kanban.destroy();
+ })
+ .on('cycle', function(event) {
+ assert.ok(true, String(event.target));
+ })
+ .on('complete', done)
+ .run({ 'async': true });
+ };
+ }
+}, function () {
+ QUnit.test('simple kanban view with 2 records', function (assert) {
+ var done = assert.async();
+ assert.expect(1);
+
+ this.arch = '<kanban class="o_kanban_test"><templates><t t-name="kanban-box">' +
+ '<div>' +
+ '<t t-esc="record.foo.value"/>' +
+ '<field name="foo"/>' +
+ '</div>' +
+ '</t></templates></kanban>';
+
+ this.run(assert, done);
+ });
+
+ QUnit.test('simple kanban view with 200 records', function (assert) {
+ var done = assert.async();
+ assert.expect(1);
+
+ for (var i = 2; i < 200; i++) {
+ this.data.foo.records.push({
+ id: i,
+ foo: "automated data" + i,
+ });
+ }
+
+ this.arch = '<kanban class="o_kanban_test"><templates><t t-name="kanban-box">' +
+ '<div>' +
+ '<t t-esc="record.foo.value"/>' +
+ '<field name="foo"/>' +
+ '</div>' +
+ '</t></templates></kanban>';
+
+ this.run(assert, done);
+ });
+
+});
+});
diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js
index debb65b60ff..7f853138265 100644
--- a/addons/web/static/tests/views/kanban_tests.js
+++ b/addons/web/static/tests/views/kanban_tests.js
@@ -586,7 +586,7 @@ QUnit.module('Views', {
});
QUnit.test('create a column in grouped on m2o', function (assert) {
- assert.expect(12);
+ assert.expect(13);
var nbRPCs = 0;
var kanban = createView({
@@ -606,7 +606,7 @@ QUnit.module('Views', {
assert.ok(true, "should call name_create");
}
return this._super(route, args);
- }
+ },
});
assert.strictEqual(kanban.$('.o_column_quick_create').length, 1, "should have a quick create column");
assert.notOk(kanban.$('.o_column_quick_create input').is(':visible'),
@@ -645,11 +645,47 @@ QUnit.module('Views', {
assert.ok(!kanban.$('.o_kanban_group:last').hasClass('o_column_folded'),
'the created column should not be folded');
assert.strictEqual(nbRPCs, 0, 'no rpc should have been done when folding/unfolding');
+
+ // quick create a record
+ kanban.$buttons.find('.o-kanban-button-new').click(); // Click on 'Create'
+ assert.ok(kanban.$('.o_kanban_group:first() > div:nth(1)').hasClass('o_kanban_quick_create'),
+ "clicking on create should open the quick_create in the first column");
kanban.destroy();
});
+ QUnit.test('quick create record & column in grouped on m2o', function (assert) {
+ assert.expect(2);
+
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch: '<kanban on_create="quick_create">' +
+ '<field name="product_id"/>' +
+ '<templates><t t-name="kanban-box">' +
+ '<div><field name="foo"/></div>' +
+ '</t></templates>' +
+ '</kanban>',
+ groupBy: ['product_id'],
+ });
+ kanban.$('.o_kanban_group:first .o_kanban_quick_add').click();
+ var $quickCreate = kanban.$('.o_kanban_quick_create');
+ $quickCreate.find('input').val('new partner');
+ $quickCreate.find('button.o_kanban_add').click();
+ assert.strictEqual(this.data.partner.records.length, 5,
+ "should have created a partner");
+
+ kanban.$('.o_column_quick_create').click();
+ kanban.$('.o_column_quick_create input').val('new column');
+ kanban.$('.o_column_quick_create button.o_kanban_add').click();
+
+ assert.strictEqual(kanban.$('.o_kanban_group:last span:contains(new column)').length, 1,
+ "the last column should be the newly created one");
+ kanban.destroy();
+ }),
+
QUnit.test('delete a column in grouped on m2o', function (assert) {
- assert.expect(25);
+ assert.expect(26);
var kanban = createView({
View: KanbanView,
@@ -719,8 +755,49 @@ QUnit.module('Views', {
assert.ok(!kanban.$('.o_kanban_header:first .o_kanban_config .o_column_unarchive').length,
"should not be able to restore the records");
assert.verifySteps(['read_group', 'unlink', 'read_group']);
+ assert.strictEqual(kanban.renderer.widgets.length, 2,
+ "the old widgets should have been correctly deleted");
kanban.destroy();
- });
+ }),
+
+ QUnit.test('create a column, delete it and create another one', function (assert) {
+ assert.expect(5);
+
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch: '<kanban on_create="quick_create">' +
+ '<field name="product_id"/>' +
+ '<templates><t t-name="kanban-box">' +
+ '<div><field name="foo"/></div>' +
+ '</t></templates>' +
+ '</kanban>',
+ groupBy: ['product_id'],
+ });
+
+ assert.strictEqual(kanban.$('.o_kanban_group').length, 2, "should have two columns");
+
+ kanban.$('.o_column_quick_create').click();
+ kanban.$('.o_column_quick_create input').val('new column 1');
+ kanban.$('.o_column_quick_create button.o_kanban_add').click();
+
+ assert.strictEqual(kanban.$('.o_kanban_group').length, 3, "should have two columns");
+
+ kanban.$('.o_kanban_group:last .o_column_delete').click();
+ $('.modal .modal-footer .btn-primary').click();
+
+ assert.strictEqual(kanban.$('.o_kanban_group').length, 2, "should have twos columns");
+
+ kanban.$('.o_column_quick_create').click();
+ kanban.$('.o_column_quick_create input').val('new column 2');
+ kanban.$('.o_column_quick_create button.o_kanban_add').click();
+
+ assert.strictEqual(kanban.$('.o_kanban_group').length, 3, "should have three columns");
+ assert.strictEqual(kanban.$('.o_kanban_group:last span:contains(new column 2)').length, 1,
+ "the last column should be the newly created one");
+ kanban.destroy();
+ }),
QUnit.test('edit a column in grouped on m2o', function (assert) {
assert.expect(12);
@@ -1375,6 +1452,33 @@ QUnit.module('Views', {
kanban.destroy();
});
+ QUnit.test('update buttons after column creation', function (assert) {
+ assert.expect(2);
+
+ this.data.partner.records = [];
+
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch: '<kanban>' +
+ '<templates><t t-name="kanban-box">' +
+ '<div><field name="foo"/></div>' +
+ '</t></templates></kanban>',
+ groupBy: ['product_id'],
+ });
+
+ assert.ok(kanban.$buttons.find('.o-kanban-button-new').hasClass('btn-default'),
+ "Create button shouldn't be highlighted");
+
+ kanban.$('.o_column_quick_create').click();
+ kanban.$('.o_column_quick_create input').val('new column');
+ kanban.$('.o_column_quick_create button.o_kanban_add').click();
+
+ assert.ok(kanban.$buttons.find('.o-kanban-button-new').hasClass('btn-primary'),
+ "Create button should now be highlighted");
+ kanban.destroy();
+ });
});
});
diff --git a/addons/web/static/tests/views/list_benchmarks.js b/addons/web/static/tests/views/list_benchmarks.js
new file mode 100644
index 00000000000..7b4e1f7e0c7
--- /dev/null
+++ b/addons/web/static/tests/views/list_benchmarks.js
@@ -0,0 +1,102 @@
+odoo.define('web.list_benchmarks', function (require) {
+"use strict";
+
+var ListView = require('web.ListView');
+var testUtils = require('web.test_utils');
+
+var createView = testUtils.createView;
+
+QUnit.module('List View', {
+ beforeEach: function () {
+ this.data = {
+ foo: {
+ fields: {
+ foo: {string: "Foo", type: "char"},
+ bar: {string: "Bar", type: "boolean"},
+ int_field: {string: "int_field", type: "integer", sortable: true},
+ qux: {string: "my float", type: "float"},
+ },
+ records: [
+ { id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4},
+ {id: 2, bar: true, foo: "blip", int_field: 9, qux: 13},
+ ]
+ },
+ };
+ this.arch = null;
+ this.run = function (assert, done) {
+ var data = this.data;
+ var arch = this.arch;
+ new Benchmark.Suite({})
+ .add('list', function () {
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: data,
+ arch: arch,
+ });
+ list.destroy();
+ })
+ .on('cycle', function(event) {
+ assert.ok(true, String(event.target));
+ })
+ .on('complete', done)
+ .run({ 'async': true });
+ };
+ }
+}, function () {
+ QUnit.test('simple readonly list with 2 rows and 2 fields', function (assert) {
+ var done = assert.async();
+ assert.expect(1);
+
+ this.arch ='<tree><field name="foo"/><field name="int_field"/></tree>';
+ this.run(assert, done);
+ });
+
+ QUnit.test('simple readonly list with 200 rows and 2 fields', function (assert) {
+ var done = assert.async();
+ assert.expect(1);
+
+ for (var i = 2; i < 200; i++) {
+ this.data.foo.records.push({
+ id: i,
+ foo: "automated data",
+ int_field: 10 * i,
+ });
+ }
+ this.arch ='<tree><field name="foo"/><field name="int_field"/></tree>';
+ this.run(assert, done);
+ });
+
+ QUnit.test('simple readonly list with 200 rows and 2 fields (with widgets)', function (assert) {
+ var done = assert.async();
+ assert.expect(1);
+
+ for (var i = 2; i < 200; i++) {
+ this.data.foo.records.push({
+ id: i,
+ foo: "automated data",
+ int_field: 10 * i,
+ });
+ }
+ this.arch = '<tree><field name="foo" widget="char"/><field name="int_field" widget="integer"/></tree>';
+ this.run(assert, done);
+ });
+
+ QUnit.test('simple readonly list with 200 rows 4 fields', function (assert) {
+ var done = assert.async();
+ assert.expect(1);
+
+ for (var i = 2; i < 200; i++) {
+ this.data.foo.records.push({
+ id: i,
+ foo: "automated data",
+ int_field: 10 * i,
+ bar: i % 2 === 0,
+ });
+ }
+ this.arch = '<tree><field name="foo"/><field name="int_field"/><field name="bar"/><field name="qux"/></tree>';
+ this.run(assert, done);
+ });
+
+});
+});
diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js
index 5b507871734..a74192731ec 100644
--- a/addons/web/static/tests/views/list_tests.js
+++ b/addons/web/static/tests/views/list_tests.js
@@ -711,6 +711,33 @@ QUnit.module('Views', {
list.destroy();
});
+ QUnit.test('use more complex default_order', function (assert) {
+ assert.expect(3);
+
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: this.data,
+ arch: '<tree default_order="foo, bar desc, int_field">' +
+ '<field name="foo"/><field name="bar"/>' +
+ '</tree>',
+ mockRPC: function (route, args) {
+ if (route === '/web/dataset/search_read') {
+ assert.strictEqual(args.sort, 'foo ASC, bar DESC, int_field ASC',
+ "should correctly set the sort attribute");
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+
+ assert.ok(list.$('tbody tr:first td:contains(blip)').length,
+ "record 3 should be first");
+ assert.ok(list.$('tbody tr:eq(3) td:contains(yop)').length,
+ "record 1 should be first");
+
+ list.destroy();
+ });
+
QUnit.test('can display button in edit mode', function (assert) {
assert.expect(1);
@@ -1970,6 +1997,175 @@ QUnit.module('Views', {
"next field (checkbox) should now be focused");
list.destroy();
});
+
+ QUnit.test('navigation: moving left/right with keydown', function (assert) {
+ assert.expect(8);
+
+ this.data.foo.fields.foo.type = 'text';
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: this.data,
+ arch:
+ '<tree editable="bottom">' +
+ '<field name="m2m" widget="many2many_tags"/>' +
+ '<field name="foo"/>' +
+ '<field name="bar"/>' +
+ '<field name="m2o"/>' +
+ '<field name="qux"/>' +
+ '</tree>',
+ });
+
+ list.$('td:contains(13)').click();
+ var $m2m = list.$('[name="m2m"] input');
+ var $foo = list.$('textarea[name="foo"]');
+ var $bar = list.$('[name="bar"] input');
+ var $m2o = list.$('[name="m2o"] input');
+ var $qux = list.$('input[name="qux"]');
+
+ assert.strictEqual(document.activeElement, $qux[0],
+ "'qux' input should be focused");
+
+ $qux[0].selectionEnd = 0; // Simulate browser keyboard left behavior (unselect)
+ $qux.trigger({type: 'keydown', which: $.ui.keyCode.LEFT});
+ assert.strictEqual(document.activeElement, $m2o[0],
+ "'m2o' input should be focused");
+
+ // forget unselecting and try leaving
+ $m2o.trigger({type: 'keydown', which: $.ui.keyCode.LEFT});
+ assert.strictEqual(document.activeElement, $m2o[0],
+ "'m2o' input should still be focused");
+
+ $m2o[0].selectionEnd = 0; // Simulate browser keyboard left behavior (unselect)
+ $m2o.trigger({type: 'keydown', which: $.ui.keyCode.LEFT});
+ assert.strictEqual(document.activeElement, $bar[0],
+ "'bar' input should be focused");
+
+ // no unselect here as it is a checkbox
+ $bar.trigger({type: 'keydown', which: $.ui.keyCode.LEFT});
+ assert.strictEqual(document.activeElement, $foo[0],
+ "'foo' input should be focused");
+
+ // forget unselecting and try leaving
+ $foo.trigger({type: 'keydown', which: $.ui.keyCode.LEFT});
+ assert.strictEqual(document.activeElement, $foo[0],
+ "'foo' input should still be focused");
+
+ $foo[0].selectionEnd = 0; // Simulate browser keyboard left behavior (unselect)
+ $foo.trigger({type: 'keydown', which: $.ui.keyCode.LEFT});
+ assert.strictEqual(document.activeElement, $m2m[0],
+ "'m2m' input should be focused");
+
+ $m2m[0].selectionStart = $m2m[0].value.length; // Simulate browser keyboard right behavior (unselect)
+ $m2m.trigger({type: 'keydown', which: $.ui.keyCode.RIGHT});
+ assert.strictEqual(document.activeElement, $foo[0],
+ "'foo' input should be focused");
+
+ list.destroy();
+ });
+
+ QUnit.test('discarding changes in a row properly updates the rendering', function (assert) {
+ assert.expect(3);
+
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: this.data,
+ arch:
+ '<tree editable="top">' +
+ '<field name="foo"/>' +
+ '</tree>',
+ });
+
+ assert.strictEqual(list.$('.o_data_cell:first').text(), "yop",
+ "first cell should contain 'yop'");
+
+ list.$('.o_data_cell:first').click();
+ list.$('input[name="foo"]').val("hello").trigger('input');
+ list.$buttons.find('.o_list_button_discard').click();
+ assert.strictEqual($('.modal:visible').length, 1,
+ "a modal to ask for discard should be visible");
+
+ $('.modal:visible .btn-primary').click();
+ assert.strictEqual(list.$('.o_data_cell:first').text(), "yop",
+ "first cell should still contain 'yop'");
+
+ list.destroy();
+ });
+
+ QUnit.test('numbers in list are right-aligned', function (assert) {
+ assert.expect(2);
+
+ var currencies = {};
+ _.each(this.data.res_currency.records, function (currency) {
+ currencies[currency.id] = currency;
+ });
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: this.data,
+ arch:
+ '<tree editable="top">' +
+ '<field name="foo"/>' +
+ '<field name="qux"/>' +
+ '<field name="amount" widget="monetary"/>' +
+ '<field name="currency_id" invisible="1"/>' +
+ '</tree>',
+ session: {
+ currencies: currencies,
+ },
+ });
+
+ var nbCellRight = _.filter(list.$('.o_data_row:first > .o_data_cell'), function (el) {
+ var style = window.getComputedStyle(el);
+ return style.textAlign === 'right';
+ }).length;
+ assert.strictEqual(nbCellRight, 2,
+ "there should be two right-aligned cells");
+
+ list.$('.o_data_cell:first').click();
+
+ var nbInputRight = _.filter(list.$('.o_data_row:first > .o_data_cell input'), function (el) {
+ var style = window.getComputedStyle(el);
+ return style.textAlign === 'right';
+ }).length;
+ assert.strictEqual(nbInputRight, 2,
+ "there should be two right-aligned input");
+
+ list.destroy();
+ });
+
+ QUnit.test('grouped list are not editable', function (assert) {
+ // Editable grouped list views are not supported, so the purpose of this
+ // test is to check that when a list view is grouped, its editable
+ // attribute is ignored
+ assert.expect(4);
+
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: this.data,
+ arch: '<tree editable="top"><field name="foo"/><field name="bar"/></tree>',
+ intercepts: {
+ switch_view: function () {
+ assert.step('switch view');
+ },
+ },
+ });
+
+ list.$('.o_data_cell:first').click();
+ assert.verifySteps([], 'no switch view should have been requested');
+ assert.strictEqual(list.$('.o_selected_row').length, 1,
+ "a row should be in edition");
+
+ // reload with groupBy
+ list.reload({groupBy: ['bar']});
+ list.$('.o_group_header:first').click();
+ list.$('.o_data_cell:first').click();
+ assert.verifySteps(['switch view'], 'one switch view should have been requested');
+
+ list.destroy();
+ });
});
});
diff --git a/addons/web/static/tests/views/view_dialogs_tests.js b/addons/web/static/tests/views/view_dialogs_tests.js
index 2a86f044af0..963b3c1552e 100644
--- a/addons/web/static/tests/views/view_dialogs_tests.js
+++ b/addons/web/static/tests/views/view_dialogs_tests.js
@@ -46,6 +46,11 @@ QUnit.module('Views', {
},
});
+ testUtils.intercept(parent, 'env_updated', function () {
+ throw new Error("The environment should not be propagated to the view manager");
+ });
+
+
var dialog = new dialogs.FormViewDialog(parent, {
res_model: 'partner',
res_id: 1,
diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml
index 434cc728769..dee21aa3129 100644
--- a/addons/web/views/webclient_templates.xml
+++ b/addons/web/views/webclient_templates.xml
@@ -65,6 +65,7 @@
<script type="text/javascript" src="/web/static/src/js/core/collections.js"/>
<script type="text/javascript" src="/web/static/src/js/core/translation.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/ajax.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/services/ajax_service.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/time.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/mixins.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/rpc.js"></script>
@@ -145,7 +146,6 @@
<script type="text/javascript" src="/web/static/src/js/_deprecated/data.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/context.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/misc.js"></script>
- <script type="text/javascript" src="/web/static/src/js/services/ajax_service.js"></script>
<script type="text/javascript" src="/web/static/src/js/services/crash_manager.js"></script>
<script type="text/javascript" src="/web/static/src/js/services/data_manager.js"></script>
<script type="text/javascript" src="/web/static/src/js/services/session.js"></script>
@@ -469,6 +469,60 @@
</t>
</template>
+ <template id="web.benchmark_suite">
+ <t t-call="web.layout">
+ <t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
+ <t t-set="title">Web Benchmarks</t>
+ <t t-set="head">
+ <link type="text/css" rel="stylesheet" href="/web/static/lib/qunit/qunit-2.2.1.css"/>
+ <script type="text/javascript" src="/web/static/lib/qunit/qunit-2.2.1.js"></script>
+ <script type="text/javascript" src="/web/static/tests/helpers/qunit_config.js"></script>
+ <script type="text/javascript" src="/web/static/lib/benchmarkjs/lodash.js"></script>
+ <script type="text/javascript" src="/web/static/lib/benchmarkjs/benchmark.js"></script>
+
+ <t t-call-assets="web.assets_common" t-js="false"/>
+ <t t-call-assets="web.assets_backend" t-js="false"/>
+ <t t-call-assets="web.assets_common" t-css="false"/>
+ <t t-call-assets="web.assets_backend" t-css="false"/>
+
+ <script type="text/javascript">
+ QUnit.config.hidepassed = false;
+
+ // define the 'web.web_client' module because some other modules require it
+ odoo.define('web.web_client', function (require) {
+ var WebClient = require('web.WebClient');
+ var web_client = new WebClient();
+ // override _call_service to prevent the web_client from doing RPCs
+ web_client._call_service = function () {};
+ return web_client;
+ });
+ </script>
+
+ <style>
+ body:not(.debug) .modal-backdrop, body:not(.debug) .modal, body:not(.debug) .ui-autocomplete {
+ opacity: 0 !important;
+ }
+ #qunit-testrunner-toolbar label {
+ font-weight: inherit;
+ margin-bottom: inherit;
+ }
+ #qunit-testrunner-toolbar input[type=text] {
+ width: inherit;
+ display: inherit;
+ }
+ </style>
+ <script type="text/javascript" src="/web/static/tests/helpers/test_utils.js"></script>
+ <script type="text/javascript" src="/web/static/tests/helpers/mock_server.js"></script>
+
+ <script type="text/javascript" src="/web/static/tests/views/list_benchmarks.js"></script>
+ <script type="text/javascript" src="/web/static/tests/views/kanban_benchmarks.js"></script>
+ </t>
+
+ <div id="qunit"/>
+ <div id="qunit-fixture"/>
+ </t>
+ </template>
+
<template id="web.webclient_bootstrap">
<t t-call="web.layout">
<t t-set="head_web">
diff --git a/addons/web_editor/static/src/js/ace.js b/addons/web_editor/static/src/js/ace.js
index 4a5e4a6d824..b1b28d78e83 100644
--- a/addons/web_editor/static/src/js/ace.js
+++ b/addons/web_editor/static/src/js/ace.js
@@ -287,12 +287,15 @@ var ViewEditor = Widget.extend({
this.less = this.resources.less;
// Load resources
- return ajax.jsonRpc("/web_editor/get_assets_editor_resources", "call", {
- key: this.viewKey,
- get_views: !this.options.doNotLoadViews,
- get_less: !this.options.doNotLoadLess,
- bundles: this.options.includeBundles,
- bundles_restriction: this.options.includeAllLess ? [] : this.options.defaultBundlesRestriction,
+ return this._rpc({
+ route: "/web_editor/get_assets_editor_resources",
+ params: {
+ key: this.viewKey,
+ get_views: !this.options.doNotLoadViews,
+ get_less: !this.options.doNotLoadLess,
+ bundles: this.options.includeBundles,
+ bundles_restriction: this.options.includeAllLess ? [] : this.options.defaultBundlesRestriction,
+ },
}).then((function (resources) {
_process_views.call(this, resources.views);
_process_less.call(this, resources.less);
@@ -481,9 +484,12 @@ var ViewEditor = Widget.extend({
if (this.currentType === "xml") {
return $.Defered().reject(_t("Reseting views is not supported yet")); // TODO
} else {
- return ajax.jsonRpc("/web_editor/reset_less", "call", {
- url: resID,
- bundle_xmlid: this.less[resID].bundle_xmlid,
+ return this._rpc({
+ route: "/web_editor/reset_less",
+ params: {
+ url: resID,
+ bundle_xmlid: this.less[resID].bundle_xmlid,
+ },
});
}
},
@@ -596,7 +602,7 @@ var ViewEditor = Widget.extend({
var def = $.Deferred();
var self = this;
- ajax.jsonRpc('/web/dataset/call', 'call', {
+ this._rpc({
model: 'ir.ui.view',
method: 'write',
args: [[session.id], {arch: session.text}, _.extend(base.get_context(), {lang: null})],
@@ -618,10 +624,13 @@ var ViewEditor = Widget.extend({
var def = $.Deferred();
var self = this;
- ajax.jsonRpc("/web_editor/save_less", "call", {
- url: session.id,
- bundle_xmlid: this.less[session.id].bundle_xmlid,
- content: session.text,
+ this._rpc({
+ route: "/web_editor/save_less",
+ params: {
+ url: session.id,
+ bundle_xmlid: this.less[session.id].bundle_xmlid,
+ content: session.text,
+ },
}).then(function () {
self._toggleDirtyInfo(session.id, "less", false);
def.resolve();
diff --git a/addons/web_tour/static/src/less/tip.less b/addons/web_tour/static/src/less/tip.less
index c53ad943ff1..8f994e64ee7 100644
--- a/addons/web_tour/static/src/less/tip.less
+++ b/addons/web_tour/static/src/less/tip.less
@@ -1,6 +1,28 @@
.o_tooltip_parent {
position: relative!important;
+
+ // Tooltips are placed in the <body/> element when opened because this is
+ // the only way to position them above everything else thanks to a 1051
+ // z-index. However, for scrolling performance, the tooltip is placed in its
+ // ideal location (see Tip._get_ideal_location). When in this location, the
+ // tooltip were sometimes overlapping unwanted elements (e.g. chat windows).
+ //
+ // The z-index of the ideal locations cannot be determined safely as they
+ // are different from one tip to another. So, in the appswitcher for
+ // example, the tooltips will act as root-level z-index 1051. As the chat
+ // windows are root-level z-index 3, the tooltips will overlap in that case.
+ //
+ // Changing the opacity of the tooltip parents forces the creation of a
+ // stacking context; the appswitcher tooltips are thus now considered to be
+ // root-level z-index auto (or the default appswitcher one) and should so
+ // act like their parent (e.g. the appswitcher is below the chat windows so
+ // the inner tooltips will be too). The tips will be above all elements of
+ // the appswitcher as they still have a high z-index, but relative to the
+ // appswitcher (this is especially useful in the website where most tooltips
+ // are placed in the body and need to be placed above elements with z-index
+ // like the navbar).
+ opacity: 0.999;
}
.o_tooltip {
@@ -39,7 +61,7 @@
border: @o-tip-border-width solid @o-tip-color;
border-radius: 50%;
padding: 0; // ! Cannot be changed ! Javascript rely on this.
- z-index: @zindex-modal+1;
+ z-index: @zindex-modal + 1; // See comment on 'o_tooltip_parent' class
background-color: @o-tip-color;
box-shadow: 0 2px 2px 1px rgba(150, 150, 150, 0.3);
diff --git a/addons/website/static/src/js/website.snippets.animation.js b/addons/website/static/src/js/website.snippets.animation.js
index e4dd19e03db..ed4b810179c 100644
--- a/addons/website/static/src/js/website.snippets.animation.js
+++ b/addons/website/static/src/js/website.snippets.animation.js
@@ -520,52 +520,71 @@ animation.registry.gallery = animation.Class.extend({
animation.registry.gallery_slider = animation.Class.extend({
selector: ".o_slideshow",
- start: function () {
- var $carousel = this.$target.is(".carousel") ? this.$target : this.$target.find(".carousel");
- var $indicator = $carousel.find('.carousel-indicators');
- var $lis = $indicator.find('li:not(.fa)');
- var $prev = $indicator.find('li.fa:first');
- var $next = $indicator.find('li.fa:last');
- var index = ($lis.filter('.active').index() || 1) -1;
- var page = Math.floor(index / 10);
- var nb = Math.ceil($lis.length / 10);
-
- // fix bootstrap use index insead of data-slide-to
- $carousel.on('slide.bs.carousel', function () {
+ start: function (editable_mode) {
+ var self = this;
+ this.$carousel = this.$target.is(".carousel") ? this.$target : this.$target.find(".carousel");
+ this.$indicator = this.$carousel.find('.carousel-indicators');
+ this.$prev = this.$indicator.find('li.fa:first').css('visibility', ''); // force visibility as some databases have it hidden
+ this.$next = this.$indicator.find('li.fa:last').css('visibility', '');
+ var $lis = this.$indicator.find('li:not(.fa)');
+ var nbPerPage = Math.floor(this.$indicator.width() / $lis.first().outerWidth(true)) - 3; // - navigator - 1 to leave some space
+ var realNbPerPage = nbPerPage || 1;
+ var nbPages = Math.ceil($lis.length / realNbPerPage);
+
+ var index;
+ var page;
+ update();
+
+ function hide() {
+ $lis.each(function (i) {
+ $(this).toggleClass('hidden', !(i >= page*nbPerPage && i < (page+1)*nbPerPage));
+ });
+ if (editable_mode) { // do not remove DOM in edit mode
+ return;
+ }
+ if (page <= 0) {
+ self.$prev.detach();
+ } else {
+ self.$prev.prependTo(self.$indicator);
+ }
+ if (page >= nbPages - 1) {
+ self.$next.detach();
+ } else {
+ self.$next.appendTo(self.$indicator);
+ }
+ }
+
+ function update() {
+ index = $lis.index($lis.filter('.active')) || 0;
+ page = Math.floor(index / realNbPerPage);
+ hide();
+ }
+
+ this.$carousel.on('slide.bs.carousel.gallery_slider', function () {
setTimeout(function () {
- var $item = $carousel.find('.carousel-inner .prev, .carousel-inner .next');
+ var $item = self.$carousel.find('.carousel-inner .prev, .carousel-inner .next');
var index = $item.index();
$lis.removeClass("active")
.filter('[data-slide-to="'+index+'"]')
.addClass("active");
- },0);
- });
-
- function hide () {
- $lis.addClass('hidden').each(function (i) {
- if (i >= page*10 && i < (page+1)*10) {
- $(this).removeClass('hidden');
- }
- });
- $prev.css('visibility', page === 0 ? 'hidden' : '');
- $next.css('visibility', (page+1) >= nb ? 'hidden' : '');
- }
-
- $indicator.find('li.fa').on('click', function () {
- page = (page + ($(this).hasClass('o_indicators_left')?-1:1)) % nb;
- $carousel.carousel(page*10);
- hide();
+ }, 0);
});
- hide();
-
- $carousel.on('slid.bs.carousel', function () {
- var index = ($lis.filter('.active').index() || 1) -1;
- page = Math.floor(index / 10);
+ this.$indicator.on('click.gallery_slider', '> li.fa', function () {
+ page += ($(this).hasClass('o_indicators_left') ? -1 : 1);
+ page = Math.max(0, Math.min(nbPages - 1, page)); // should not be necessary
+ self.$carousel.carousel(page * realNbPerPage);
hide();
});
+ this.$carousel.on('slid.bs.carousel.gallery_slider', update);
+ },
+ stop: function () {
+ this._super.apply(this, arguments);
- return this._super.apply(this, arguments);
- }
+ this.$prev.prependTo(this.$indicator);
+ this.$next.appendTo(this.$indicator);
+ this.$carousel.off('.gallery_slider');
+ this.$indicator.off('.gallery_slider');
+ },
});
});
diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js
index 40be63e3b9d..083ed195905 100644
--- a/addons/website/static/src/js/website.snippets.editor.js
+++ b/addons/website/static/src/js/website.snippets.editor.js
@@ -223,9 +223,6 @@ options.registry.carousel = options.registry.slider.extend({
// set background and prepare to clean for save
this.$target.on('slid.bs.carousel', function () {
- self.editor.styles.background_position.$target = self.editor.styles.background.$target;
- self.editor.styles.background_position.set_active();
- self.editor.styles.background.$target.trigger("snippet-option-change", [self.editor.styles.background]);
self.$target.carousel("pause");
if (!self.editor) return;
diff --git a/addons/website/static/src/less/website.snippets.less b/addons/website/static/src/less/website.snippets.less
index 4fce9f14246..5f96bbac0e6 100644
--- a/addons/website/static/src/less/website.snippets.less
+++ b/addons/website/static/src/less/website.snippets.less
@@ -324,9 +324,6 @@ div.carousel .container {
max-height: 100%;
max-width: 100%;
margin: auto;
- position: relative;
- top: 50%;
- .translate(0, -50%);
}
ul.carousel-indicators {
@@ -357,6 +354,10 @@ div.carousel .container {
filter: gray;
filter: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' /></filter></svg>#greyscale");
}
+
+ &:first-child {
+ margin-left: 0;
+ }
}
}
diff --git a/addons/website_event/models/event.py b/addons/website_event/models/event.py
index 640eb9a3121..8fab469c5c8 100644
--- a/addons/website_event/models/event.py
+++ b/addons/website_event/models/event.py
@@ -57,7 +57,14 @@ class Event(models.Model):
if self.event_type_id:
self.website_menu = self.event_type_id.website_menu
+ def _get_standard_menu_entries_names(self):
+ """ Method returning menu entries possibly generated by event modules.
+ It is used to distinguish module-generated pages from custom pages. """
+ return [_('Introduction'), _('Location'), _('Register')]
+
def _get_menu_entries(self):
+ """ Method returning menu entries to display on the website view of the
+ event, possibly depending on some options in inheriting modules. """
self.ensure_one()
return [
(_('Introduction'), False, 'website_event.template_intro'),
@@ -75,9 +82,17 @@ class Event(models.Model):
root_menu = self.env['website.menu'].create({'name': event.name})
event.menu_id = root_menu
+ existing_page_names = event.menu_id.child_id.mapped('name')
+ required_page_names = [entry[0] for entry in self._get_menu_entries()]
+ standard_page_names = self._get_standard_menu_entries_names()
+
+ # remove entries that should not exist anymore
+ submenu_to_delete = event.menu_id.child_id.filtered(lambda menu: menu.name not in required_page_names and menu.name in standard_page_names)
+ submenu_to_delete.unlink()
+
+ # create missing entries
for sequence, (name, url, xml_id) in enumerate(self._get_menu_entries()):
- existing_pages = event.menu_id.child_id.mapped('name')
- if name not in existing_pages:
+ if name not in existing_page_names:
if not url:
newpath = self.env['website'].new_page(name + ' ' + self.name, xml_id, ispage=False)
url = "/event/" + slug(self) + "/page/" + newpath
diff --git a/addons/website_event_track/models/event.py b/addons/website_event_track/models/event.py
index 3acd8e8279f..baae681bc7b 100644
--- a/addons/website_event_track/models/event.py
+++ b/addons/website_event_track/models/event.py
@@ -80,6 +80,21 @@ class Event(models.Model):
self.website_track = False
self.website_track_proposal = False
+ @api.onchange('website_track')
+ def _onchange_website_track(self):
+ if not self.website_track:
+ self.website_track_proposal = False
+
+ @api.onchange('website_track_proposal')
+ def _onchange_website_track_proposal(self):
+ if self.website_track_proposal:
+ self.website_track = True
+
+ def _get_standard_menu_entries_names(self):
+ res = super(Event, self)._get_standard_menu_entries_names()
+ res += [_('Talks'), _('Agenda'), _('Talk Proposals')]
+ return res
+
def _get_menu_entries(self):
self.ensure_one()
res = super(Event, self)._get_menu_entries()
diff --git a/addons/website_form/controllers/main.py b/addons/website_form/controllers/main.py
index cf70e0dd62a..cdf1034c7a9 100644
--- a/addons/website_form/controllers/main.py
+++ b/addons/website_form/controllers/main.py
@@ -171,7 +171,7 @@ class WebsiteForm(http.Controller):
return data
def insert_record(self, request, model, values, custom, meta=None):
- record = request.env[model.model].sudo().create(values)
+ record = request.env[model.model].sudo().with_context(mail_create_nosubscribe=True).create(values)
if custom or meta:
default_field = model.website_form_default_field_id
diff --git a/addons/website_mail_channel/controllers/main.py b/addons/website_mail_channel/controllers/main.py
index 9a64504e309..c9b3deb268e 100644
--- a/addons/website_mail_channel/controllers/main.py
+++ b/addons/website_mail_channel/controllers/main.py
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+import werkzeug
+
from datetime import datetime
from dateutil import relativedelta
@@ -119,6 +121,9 @@ class MailGroup(http.Controller):
"/groups/<model('mail.channel'):group>/page/<int:page>"
], type='http', auth="public", website=True)
def thread_headers(self, group, page=1, mode='thread', date_begin=None, date_end=None, **post):
+ if group.channel_type != 'channel':
+ raise werkzeug.exceptions.NotFound()
+
Message = request.env['mail.message']
domain = [('model', '=', 'mail.channel'), ('res_id', '=', group.id), ('message_type', '!=', 'notification')]
@@ -151,6 +156,9 @@ class MailGroup(http.Controller):
'''/groups/<model('mail.channel'):group>/<model('mail.message', "[('model','=','mail.channel'), ('res_id','=',group[0])]"):message>''',
], type='http', auth="public", website=True)
def thread_discussion(self, group, message, mode='thread', date_begin=None, date_end=None, **post):
+ if group.channel_type != 'channel':
+ raise werkzeug.exceptions.NotFound()
+
Message = request.env['mail.message']
if mode == 'thread':
base_domain = [('model', '=', 'mail.channel'), ('res_id', '=', group.id), ('parent_id', '=', message.parent_id and message.parent_id.id or False)]
@@ -175,6 +183,9 @@ class MailGroup(http.Controller):
'''/groups/<model('mail.channel'):group>/<model('mail.message', "[('model','=','mail.channel'), ('res_id','=',group[0])]"):message>/get_replies''',
type='json', auth="public", methods=['POST'], website=True)
def render_messages(self, group, message, **post):
+ if group.channel_type != 'channel':
+ return False
+
last_displayed_id = post.get('last_displayed_id')
if not last_displayed_id:
return False
diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml
index adc88e4a140..ec1c57ae130 100644
--- a/addons/website_sale/views/templates.xml
+++ b/addons/website_sale/views/templates.xml
@@ -465,7 +465,7 @@
<a id="add_to_cart" class="btn btn-primary btn-lg mt8 js_check_product a-submit" href="#">Add to Cart</a>
</div>
</form>
- <hr />
+ <hr t-if="product.availability != 'empty'"/>
<div t-if="product.availability == 'in_stock'" class="alert alert-success">
<span class="fa fa-check" />
<span>In Stock</span>
@@ -1435,7 +1435,7 @@
<div class="col-sm-12">
<form target="_self" action="/shop/payment/validate" method="post" class="pull-right">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
- <a style="width:127px;" class="btn btn-primary a-submit">
+ <a class="btn btn-primary a-submit">
<span t-if="order.amount_total &gt; 0">Pay Now <span class="fa fa-long-arrow-right"></span></span>
<span t-if="order.amount_total == 0">Confirm Order <span class="fa fa-long-arrow-right"></span></span>
</a>