odoo.define("account.reconciliation_tests.data", function () {
"use strict";
/*
* Debug tip:
* To be able to "see" the test in the browser:
* var $body = $('body');
* $body.addClass('debug');
* clientAction.appendTo($body);
*/
var Datas = {};
var db = {
"res.company": {
fields: {
id: {string: "ID", type: "integer"},
display_name: {string: "Displayed name", type: "char"},
},
records: [{id: 1, display_name: "company 1"}],
},
"res.partner": {
fields: {
id: {string: "ID", type: "integer"},
display_name: {string: "Displayed name", type: "char"},
image: {string: "image", type: "integer"},
parent_id: {string: "Parent", type: "boolean"},
is_company: {string: "Is company", type: "boolean"},
property_account_receivable_id: {
string: "Account receivable",
type: "many2one",
relation: "account.account",
},
property_account_payable_id: {
string: "Account payable",
type: "many2one",
relation: "account.account",
},
},
records: [
{id: 1, display_name: "partner 1", image: "AAA"},
{id: 2, display_name: "partner 2", image: "BBB"},
{id: 3, display_name: "partner 3", image: "CCC"},
{id: 4, display_name: "partner 4", image: "DDD"},
{id: 8, display_name: "Agrolait", image: "EEE"},
{
id: 12,
display_name: "Camptocamp",
image: "FFF",
property_account_receivable_id: 287,
property_account_payable_id: 287,
},
// Add more to have 'Search More' option
{id: 98, display_name: "partner 98", image: "YYY"},
{id: 99, display_name: "partner 99", image: "ZZZ"},
],
mark_as_reconciled: function () {
return Promise.resolve();
},
},
"account.account": {
fields: {
id: {string: "ID", type: "integer"},
code: {string: "code", type: "integer"},
name: {string: "Displayed name", type: "char"},
company_id: {
string: "Company",
type: "many2one",
relation: "res.company",
},
deprecated: {string: "Deprecated", type: "boolean"},
},
records: [
{
id: 282,
code: 100000,
name: "100000 Fixed Asset Account",
company_id: 1,
},
{id: 283, code: 101000, name: "101000 Current Assets", company_id: 1},
{
id: 284,
code: 101110,
name: "101110 Stock Valuation Account",
company_id: 1,
},
{
id: 285,
code: 101120,
name: "101120 Stock Interim Account (Received)",
company_id: 1,
},
{
id: 286,
code: 101130,
name: "101130 Stock Interim Account (Delivered)",
company_id: 1,
},
{
id: 287,
code: 101200,
name: "101200 Account Receivable",
company_id: 1,
},
{id: 288, code: 101300, name: "101300 Tax Paid", company_id: 1},
{id: 308, code: 101401, name: "101401 Bank", company_id: 1},
{id: 499, code: 499001, name: "499001 Suspense Account", company_id: 1},
{id: 500, code: 500, name: "500 Account", company_id: 1},
{id: 501, code: 501, name: "501 Account", company_id: 1},
{id: 502, code: 502, name: "502 Account", company_id: 1},
{id: 503, code: 503, name: "503 Account", company_id: 1},
{id: 504, code: 504, name: "504 Account", company_id: 1},
],
mark_as_reconciled: function () {
return Promise.resolve();
},
},
"account.account.tag": {
fields: {
id: {string: "ID", type: "integer"},
},
records: [{id: 1}, {id: 2}, {id: 3}, {id: 4}],
},
"account.tax.repartition.line": {
fields: {
id: {string: "ID", type: "integer"},
repartition_type: {string: "Repartition Type", type: "selection"},
account_id: {
string: "Account",
type: "many2one",
relation: "account.account",
},
factor_percent: {string: "%", type: "integer"},
tag_ids: {
string: "Tax Grids",
type: "many2many",
relation: "account.account.tag",
},
},
records: [
{id: 1, factor_percent: 100, repartition_type: "base", tag_ids: [1]},
{id: 2, factor_percent: 100, repartition_type: "tax", tag_ids: [2]},
{id: 3, factor_percent: 100, repartition_type: "base", tag_ids: [3]},
{
id: 4,
factor_percent: 100,
repartition_type: "tax",
tag_ids: [4],
account_id: 288,
},
],
},
"account.tax": {
fields: {
id: {string: "ID", type: "integer"},
display_name: {string: "Displayed name", type: "char"},
amount: {string: "amout", type: "float"},
price_include: {string: "Included in Price", type: "boolean"},
company_id: {
string: "Company",
type: "many2one",
relation: "res.company",
},
amount_type: {string: "type", type: "selection"},
invoice_repartition_line_ids: {
string: "Invoice Repartition",
type: "one2many",
relation: "account.tax.repartition.line",
},
// No need for refund repartition lines in our test; they're not used by reconciliation widget anyway
},
records: [
{
id: 6,
display_name: "Tax 20.00%",
amount: 20,
amount_type: "percent",
price_include: false,
company_id: 1,
invoice_repartition_line_ids: [1, 2],
},
{
id: 7,
display_name: "Tax 10.00% include",
amount: 10,
amount_type: "percent",
price_include: true,
company_id: 1,
invoice_repartition_line_ids: [3, 4],
},
],
json_friendly_compute_all: function (args) {
var tax = _.find(db["account.tax"].records, {id: args[0][0]});
var amount = args[1];
var tax_base = null;
var base_tags = null;
var taxes = [];
for (let i = 0; i < tax.invoice_repartition_line_ids.length; i++) {
var rep_ln = _.find(db["account.tax.repartition.line"].records, {
id: tax.invoice_repartition_line_ids[i],
});
if (rep_ln.repartition_type == "base") {
tax_base =
(tax.price_include
? (amount * 100) / (100 + tax.amount)
: amount) *
(rep_ln.factor_percent / 100);
base_tags = rep_ln.tag_ids;
} else if (rep_ln.repartition_type == "tax") {
/*
IMPORTANT :
For simplicity of testing, we assume there is ALWAYS a
base repartition line before the tax one, so tax_base is non-null
*/
taxes.push({
id: tax.id,
amount: (tax_base * tax.amount) / 100,
base: tax_base,
name: tax.display_name,
analytic: false,
account_id: rep_ln.account_id,
price_include: tax.price_include,
tax_repartition_line_id: rep_ln.id,
tag_ids: rep_ln.tag_ids,
tax_ids: [tax.id],
});
}
}
return Promise.resolve({
base: amount,
taxes: taxes,
base_tags: base_tags,
total_excluded: (amount / 100) * (100 - tax.amount),
total_included: amount,
});
},
},
"account.journal": {
fields: {
id: {string: "ID", type: "integer"},
display_name: {string: "Displayed name", type: "char"},
company_id: {
string: "Company",
type: "many2one",
relation: "res.company",
},
},
records: [{id: 8, display_name: "company 1 journal", company_id: 1}],
},
"account.analytic.account": {
fields: {
id: {string: "ID", type: "integer"},
display_name: {string: "Displayed name", type: "char"},
},
records: [
{id: 16, display_name: "Administrative"},
{id: 7, display_name: "Agrolait - Agrolait"},
{id: 8, display_name: "Asustek - ASUSTeK"},
{id: 15, display_name: "Camp to Camp - Camptocamp"},
{id: 6, display_name: "CampToCamp - Camptocamp"},
{id: 17, display_name: "Commercial & Marketing"},
{id: 23, display_name: "Data Import/Export Plugin - Delta PC"},
{id: 9, display_name: "Delta PC - Delta PC"},
],
},
"account.analytic.tag": {
fields: {
id: {string: "id", type: "integer"},
display_name: {string: "display_name", type: "char"},
},
records: [
{id: 1, display_name: "Come together"},
{id: 2, display_name: "Right now"},
],
},
"account.bank.statement": {
fields: {},
},
"account.bank.statement.line": {
fields: {
id: {string: "ID", type: "integer"},
display_name: {string: "Displayed name", type: "char"},
partner_id: {
string: "partner",
type: "many2one",
relation: "res.partner",
},
company_id: {
string: "Company",
type: "many2one",
relation: "res.company",
},
},
records: [
{id: 5, display_name: "SAJ/2014/002 and SAJ/2014/003", company_id: 1},
{id: 6, display_name: "Bank fees", company_id: 1},
{id: 7, display_name: "Prepayment", company_id: 1},
{
id: 8,
display_name: "First 2000 \u20ac of SAJ/2014/001",
company_id: 1,
},
],
},
"account.move.line": {
fields: {},
},
"account.reconcile.model": {
fields: {
id: {string: "ID", type: "integer"},
name: {string: "Button Label", type: "char"},
rule_type: {
string: "Type",
type: "selection",
selection: [
["writeoff_button", "Create a Button"],
["writeoff_suggestion", "Write off Suggestion"],
["invoice_matching", "Invoice matching"],
],
default: "writeoff_button",
},
has_second_line: {string: "Add a second line", type: "boolean"},
account_id: {
string: "Account",
type: "many2one",
relation: "account.account",
},
journal_id: {
string: "Journal",
type: "many2one",
relation: "account.journal",
},
label: {string: "Journal Item Label", type: "char"},
amount_type: {
string: "amount_type",
type: "selection",
selection: [
["fixed", "Fixed"],
["percentage", "Percentage of balance"],
],
default: "percentage",
},
amount: {
string: "Amount",
type: "float",
digits: 0,
help:
"Fixed amount will count as a debit if it is negative, as a credit if it is positive.",
default: 100.0,
},
tax_ids: {string: "Tax", type: "many2many", relation: "account.tax"},
analytic_account_id: {
string: "Analytic Account",
type: "many2one",
relation: "account.analytic.account",
},
second_account_id: {
string: "Second Account",
type: "many2one",
relation: "account.account",
domain: [("deprecated", "=", false)],
},
second_journal_id: {
string: "Second Journal",
type: "many2one",
relation: "account.journal",
help: "This field is ignored in a bank statement reconciliation.",
},
second_label: {string: "Second Journal Item Label", type: "char"},
second_amount_type: {
string: "Second amount_type",
type: "selection",
selection: [
["fixed", "Fixed"],
["percentage", "Percentage of balance"],
],
default: "percentage",
},
second_amount: {
string: "Second Amount",
type: "float",
digits: 0,
help:
"Fixed amount will count as a debit if it is negative, as a credit if it is positive.",
default: 100.0,
},
second_tax_ids: {
string: "Second Tax",
type: "many2many",
relation: "account.tax",
},
second_analytic_account_id: {
string: "Second Analytic Account",
type: "many2one",
relation: "account.analytic.account",
},
match_journal_ids: {
string: "Journal Ids",
type: "many2many",
relation: "account.journal",
},
analytic_tag_ids: {
string: "Analytic tags",
type: "many2many",
relation: "account.analytic.tag",
},
},
records: [
{
second_analytic_account_id: false,
second_amount_type: "percentage",
second_journal_id: false,
id: 4,
analytic_account_id: false,
display_name: "Int\u00e9rrets",
rule_type: "writeoff_button",
second_tax_ids: [],
has_second_line: false,
journal_id: false,
label: false,
second_label: false,
second_account_id: false,
account_id: 282,
company_id: [1, "Demo SPRL"],
tax_ids: [],
amount_type: "fixed",
name: "Int\u00e9rrets",
amount: 0.0,
second_amount: 100.0,
match_journal_ids: [],
},
{
second_analytic_account_id: false,
second_amount_type: "percentage",
second_journal_id: false,
id: 2,
analytic_account_id: false,
display_name: "Perte et Profit",
rule_type: "writeoff_button",
second_tax_ids: [],
has_second_line: false,
journal_id: false,
label: false,
second_label: false,
second_account_id: false,
account_id: 283,
company_id: [1, "Demo SPRL"],
tax_ids: [],
amount_type: "percentage",
name: "Perte et Profit",
amount: 100.0,
second_amount: 100.0,
match_journal_ids: [],
},
{
second_analytic_account_id: false,
second_amount_type: "percentage",
second_journal_id: false,
id: 5,
analytic_account_id: false,
display_name: "Fs bank",
rule_type: "writeoff_button",
second_tax_ids: [],
has_second_line: false,
journal_id: false,
label: false,
second_label: false,
second_account_id: false,
account_id: 284,
company_id: [1, "Demo SPRL"],
tax_ids: [],
amount_type: "percentage",
name: "Fs bank",
amount: 100.0,
second_amount: 100.0,
},
{
second_analytic_account_id: false,
second_amount_type: "percentage",
second_journal_id: false,
id: 8,
analytic_account_id: false,
display_name: "Caisse Sand.",
rule_type: "writeoff_button",
second_tax_ids: [],
has_second_line: false,
journal_id: false,
label: "Caisse Sand.",
second_label: false,
second_account_id: false,
account_id: 308,
company_id: [1, "Demo SPRL"],
tax_ids: [],
amount_type: "percentage",
name: "Caisse Sand.",
amount: 100.0,
second_amount: 100.0,
match_journal_ids: [],
},
{
second_analytic_account_id: false,
second_amount_type: "percentage",
second_journal_id: false,
id: 3,
analytic_account_id: false,
display_name: "ATOS",
rule_type: "writeoff_button",
second_tax_ids: [7],
has_second_line: true,
journal_id: false,
label: "ATOS Banque",
second_label: "ATOS Frais",
second_account_id: 286,
account_id: 285,
company_id: [1, "Demo SPRL"],
tax_ids: [6],
amount_type: "percentage",
name: "ATOS",
amount: 97.5,
second_amount: -14.75,
},
{
second_analytic_account_id: false,
second_amount_type: "percentage",
second_journal_id: false,
id: 10,
analytic_account_id: false,
display_name: "Double",
rule_type: "writeoff_button",
second_tax_ids: [],
has_second_line: true,
journal_id: false,
label: "Double Banque",
second_label: "Double Frais",
second_account_id: 286,
account_id: 285,
company_id: [1, "Demo SPRL"],
tax_ids: [],
amount_type: "percentage",
name: "Double",
amount: 97.5,
second_amount: 100,
match_journal_ids: [],
analytic_tag_ids: [1, 2],
},
],
},
"account.reconciliation.widget": {
fields: {},
auto_reconcile: function () {
return Promise.resolve(Datas.used.auto_reconciliation);
},
process_bank_statement_line: function (args) {
var datas = args[1];
var ids = _.flatten(
_.pluck(
_.pluck(datas, "counterpart_aml_dicts"),
"counterpart_aml_id"
)
);
ids = ids.concat(_.flatten(_.pluck(datas, "payment_aml_ids")));
ids = _.compact(ids);
for (var key in Datas.used.move_lines_for_manual_reconciliation) {
Datas.used.move_lines_for_manual_reconciliation[key] = _.filter(
Datas.used.move_lines_for_manual_reconciliation[key],
function (mv_line) {
return ids.indexOf(mv_line.id) === -1;
}
);
}
return Promise.resolve();
},
get_move_lines_for_bank_statement_line: function (args) {
var partner_id = args.splice(1, 1)[0];
var excluded_ids = args.splice(1, 1)[0];
var mode = args.splice(-1, 1)[0];
if (mode === "other") return Promise.resolve([]);
args.splice(-1, 1); // Ignore limit
var key = JSON.stringify(args);
if (!Datas.used.mv_lines[key]) {
throw new Error(
"Unknown parameters for get_move_lines_for_bank_statement_line: '" +
key +
"'"
);
}
var lines = Datas.used.mv_lines[key]
.filter(function (line) {
return (
excluded_ids.indexOf(line.id) === -1 &&
(!partner_id || partner_id === line.partner_id)
);
})
.map(function (line, i, src) {
line.recs_count = src.length;
return line;
})
.slice(0, options.params.limitMoveLines);
return Promise.resolve(lines);
},
get_bank_statement_line_data: function (args) {
var ids = args[0];
var results = {
value_min: 0,
value_max: ids.length,
lines: _.filter(Datas.used.data_widget, function (w) {
return _.contains(ids, w.st_line.id);
}),
};
return Promise.resolve(results);
},
get_bank_statement_data: function () {
var results = Datas.used.data_preprocess;
results.lines = _.filter(Datas.used.data_widget, function (w) {
return _.contains(results.st_lines_ids, w.st_line.id);
});
return Promise.resolve(results);
},
get_move_lines_for_manual_reconciliation: function (args) {
var excluded_ids = args.splice(2, 1)[0];
args.splice(-1, 1); // Ignore limit
var key = JSON.stringify(args);
if (!Datas.used.move_lines_for_manual_reconciliation[key]) {
throw new Error(
"Unknown parameters for get_move_lines_for_manual_reconciliation: '" +
key +
"'"
);
}
var lines = Datas.used.move_lines_for_manual_reconciliation[key]
.filter(function (line) {
return excluded_ids.indexOf(line.id) === -1;
})
.map(function (line, i, src) {
line.recs_count = src.length;
return line;
})
.slice(0, options.params.limitMoveLines);
return Promise.resolve(lines);
},
get_all_data_for_manual_reconciliation: function (args) {
var key = JSON.stringify(args);
if (!Datas.used.data_for_manual_reconciliation_widget[key]) {
throw new Error(
"Unknown parameters for get_all_data_for_manual_reconciliation: '" +
key +
"'"
);
}
return Promise.resolve(
Datas.used.data_for_manual_reconciliation_widget[key]
);
},
process_move_lines: function (args) {
var datas = args[0];
for (var i in datas) {
var data = datas[i];
for (var key in Datas.used.move_lines_for_manual_reconciliation) {
Datas.used.move_lines_for_manual_reconciliation[key] = _.filter(
Datas.used.move_lines_for_manual_reconciliation[key],
function (mv_line) {
return data.mv_line_ids.indexOf(mv_line.id) === -1;
}
);
}
}
return Promise.resolve();
},
},
};
var data_preprocess = {
value_min: 0,
value_max: 4,
notifications: [],
num_already_reconciled_lines: 0,
st_lines_ids: [5, 6, 7, 8],
statement_name: "BNK/2014/001",
};
var data_widget = [
{
st_line: {
currency_id: 3,
communication_partner_name: false,
open_balance_account_id: 287,
name: "SAJ/2014/002 and SAJ/2014/003",
partner_name: "Agrolait",
partner_id: 8,
has_no_partner: false,
journal_id: 84,
account_name: "Bank",
note: "",
amount: 1175.0,
amount_str: "$ 1,175.00",
amount_currency_str: "",
date: "2017-01-01",
account_code: "101401",
ref: "",
id: 5,
statement_id: 2,
company_id: 1,
},
reconciliation_proposition: [],
},
{
st_line: {
currency_id: 3,
communication_partner_name: false,
name: "Bank fees",
partner_name: false,
partner_id: false,
has_no_partner: true,
journal_id: 84,
account_name: "Bank",
note: "",
amount: -32.58,
amount_str: "$ 32.58",
amount_currency_str: "",
date: "2017-01-01",
account_code: "101401",
ref: "",
id: 6,
statement_id: 2,
company_id: 1,
},
reconciliation_proposition: [],
},
{
st_line: {
currency_id: 3,
communication_partner_name: false,
open_balance_account_id: 287,
name: "Prepayment",
partner_name: "Camptocamp",
partner_id: 12,
has_no_partner: false,
journal_id: 84,
account_name: "Bank",
note: "",
amount: 650.0,
amount_str: "$ 650.00",
amount_currency_str: "",
date: "2017-01-01",
account_code: "101401",
ref: "",
id: 7,
statement_id: 2,
company_id: 1,
},
reconciliation_proposition: [
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 650.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0012",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 133,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 650.00",
debit: 650.0,
account_id: [287, "101200 Account Receivable"],
account_code: "101200",
ref: "",
already_paid: false,
},
],
},
{
st_line: {
currency_id: 3,
communication_partner_name: false,
open_balance_account_id: 285,
name: "First 2000 \u20ac of SAJ/2014/001",
partner_name: "Camptocamp",
partner_id: 12,
has_no_partner: false,
journal_id: 84,
account_name: "Bank",
note: "",
amount: 2000.0,
amount_str: "$ 2,000.00",
amount_currency_str: "",
date: "2017-01-01",
account_code: "101401",
ref: "",
id: 8,
statement_id: 2,
company_id: 1,
},
reconciliation_proposition: [],
},
];
var mv_lines = {
"[]": [],
'[5,"",0]': [
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 650.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0002",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 109,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 650.00",
debit: 650.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 525.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0003",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 112,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 525.00",
debit: 525.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 650.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0012",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 134,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 650.00",
debit: 650.0,
account_id: [287, "101200 Account Receivable"],
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-01",
total_amount_str: "$ 4,610.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0001",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 106,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 4,610.00",
debit: 4610.0,
account_id: [287, "101200 Account Receivable"],
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "payable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-01",
total_amount_str: "$ 10,000.00",
partner_id: 12,
account_name: "Account Payable",
name: "BILL/2017/0001",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 114,
credit: 10000.0,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 10,000.00",
debit: 0.0,
account_id: [284, "101110 Stock Valuation Account"],
account_code: "111100",
ref: "",
already_paid: false,
},
],
'[5,"b",0]': [
{
account_type: "liquidity",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-01-23",
date: "2017-01-23",
total_amount_str: "$ 100.00",
partner_id: 8,
account_name: "Bank",
name: "BNK1/2017/0003: CUST.IN/2017/0001",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 394,
credit: 0.0,
journal_id: "Bank",
amount_str: "$ 100.00",
debit: 100.0,
account_code: "101401",
ref: "",
already_paid: true,
},
{
account_type: "liquidity",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-01-23",
date: "2017-01-23",
total_amount_str: "$ 525.50",
partner_id: 8,
account_name: "Bank",
name: "BNK1/2017/0004: CUST.IN/2017/0002",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 396,
credit: 0.0,
journal_id: "Bank",
amount_str: "$ 525.50",
debit: 525.5,
account_code: "101401",
ref: "INV/2017/0003",
already_paid: true,
},
],
'[6,"",0]': [
{
account_type: "liquidity",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-01-23",
date: "2017-01-23",
total_amount_str: "$ 376.00",
partner_id: 7,
account_name: "Bank",
name: "BNK1/2017/0002: SUPP.OUT/2017/0002",
partner_name: "ASUSTeK",
total_amount_currency_str: "",
id: 392,
credit: 376.0,
journal_id: "Bank",
amount_str: "$ 376.00",
debit: 0.0,
account_code: "101401",
ref: "BILL/2017/0003",
already_paid: true,
},
{
account_type: "liquidity",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-01-23",
date: "2017-01-23",
total_amount_str: "$ 100.00",
partner_id: 8,
account_name: "Bank",
name: "BNK1/2017/0003: CUST.IN/2017/0001",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 394,
credit: 0.0,
journal_id: "Bank",
amount_str: "$ 100.00",
debit: 100.0,
account_code: "101401",
ref: "",
already_paid: true,
},
{
account_type: "payable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-01",
total_amount_str: "$ 10,000.00",
partner_id: 12,
account_name: "Account Payable",
name: "BILL/2017/0001",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 114,
credit: 10000.0,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 10,000.00",
debit: 0.0,
account_code: "111100",
ref: "",
already_paid: false,
},
{
account_type: "liquidity",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-01-23",
date: "2017-01-23",
total_amount_str: "$ 525.50",
partner_id: 8,
account_name: "Bank",
name: "BNK1/2017/0004: CUST.IN/2017/0002",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 396,
credit: 0.0,
journal_id: "Bank",
amount_str: "$ 525.50",
debit: 525.5,
account_code: "101401",
ref: "INV/2017/0003",
already_paid: true,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 650.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0002",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 109,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 650.00",
debit: 650.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-22",
date: "2017-01-23",
total_amount_str: "$ 525.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0004",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 399,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 525.00",
debit: 525.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-01",
total_amount_str: "$ 4,610.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0001",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 106,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 4,610.00",
debit: 4610.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "payable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-15",
total_amount_str: "$ 5,749.99",
partner_id: 7,
account_name: "Account Payable",
name: "BILL/2017/0002",
partner_name: "ASUSTeK",
total_amount_currency_str: "",
id: 117,
credit: 5749.99,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 5,749.99",
debit: 0.0,
account_code: "111100",
ref: "",
already_paid: false,
},
],
'[6,"",5]': [
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-01",
total_amount_str: "$ 4,610.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0001",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 106,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 4,610.00",
debit: 4610.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "payable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-01",
total_amount_str: "$ 10,000.00",
partner_id: 12,
account_name: "Account Payable",
name: "BILL/2017/0001",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 114,
credit: 10000.0,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 10,000.00",
debit: 0.0,
account_code: "111100",
ref: "",
already_paid: false,
},
{
account_type: "payable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-15",
total_amount_str: "$ 5,749.99",
partner_id: 7,
account_name: "Account Payable",
name: "BILL/2017/0002",
partner_name: "ASUSTeK",
total_amount_currency_str: "",
id: 117,
credit: 5749.99,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 5,749.99",
debit: 0.0,
account_code: "111100",
ref: "",
already_paid: false,
},
],
'[7,"",0]': [
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 650.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0012",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 133,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 650.00",
debit: 650.0,
account_id: [287, "101200 Account Receivable"],
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-01",
total_amount_str: "$ 4,610.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0001",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 106,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 4,610.00",
debit: 4610.0,
account_id: [287, "101200 Account Receivable"],
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "payable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-28",
date: "2017-01-01",
total_amount_str: "$ 10,000.00",
partner_id: 12,
account_name: "Account Payable",
name: "BILL/2017/0001",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 114,
credit: 10000.0,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 10,000.00",
debit: 0.0,
account_id: [284, "101110 Stock Valuation Account"],
account_code: "111100",
ref: "",
already_paid: false,
},
{
account_type: "liquidity",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-01-23",
date: "2017-01-23",
total_amount_str: "$ 376.00",
partner_id: 7,
account_name: "Bank",
name: "BNK1/2017/0002: SUPP.OUT/2017/0002",
partner_name: "ASUSTeK",
total_amount_currency_str: "",
id: 392,
credit: 376.0,
journal_id: "Bank",
amount_str: "$ 376.00",
debit: 0.0,
account_code: "101401",
ref: "BILL/2017/0003",
already_paid: true,
},
{
account_type: "liquidity",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-01-23",
date: "2017-01-23",
total_amount_str: "$ 100.00",
partner_id: 8,
account_name: "Bank",
name: "BNK1/2017/0003: CUST.IN/2017/0001",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 394,
credit: 0.0,
journal_id: "Bank",
amount_str: "$ 100.00",
debit: 100.0,
account_code: "101401",
ref: "",
already_paid: true,
},
{
account_type: "liquidity",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-01-23",
date: "2017-01-23",
total_amount_str: "$ 525.50",
partner_id: 8,
account_name: "Bank",
name: "BNK1/2017/0004: CUST.IN/2017/0002",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 396,
credit: 0.0,
journal_id: "Bank",
amount_str: "$ 525.50",
debit: 525.5,
account_code: "101401",
ref: "INV/2017/0003",
already_paid: true,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 650.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0002",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 109,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 650.00",
debit: 650.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-22",
date: "2017-01-23",
total_amount_str: "$ 525.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0004",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 399,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 525.00",
debit: 525.0,
account_code: "101200",
ref: "",
already_paid: false,
},
],
'[8,"",0]': [],
};
var auto_reconciliation = {
num_already_reconciled_lines: 1,
notifications: [
{
message: "1 transaction was automatically reconciled.",
type: "info",
details: {
model: "account.move",
name: "Automatically reconciled items",
ids: [143],
},
},
],
st_lines_ids: [5, 6, 8],
statement_name: false,
};
var data_for_manual_reconciliation_widget = {
"[null,[282,283,284,285,286,287,288,308,499,500,501,502,503,504]]": {
customers: [
{
account_id: 287,
partner_name: "Agrolait",
reconciliation_proposition: [],
currency_id: 3,
max_date: "2017-02-14 12:30:31",
last_time_entries_checked: null,
account_code: "101200",
partner_id: 8,
account_name: "101200 Account Receivable",
mode: "customers",
},
{
account_id: 7,
partner_name: "Camptocamp",
reconciliation_proposition: [],
currency_id: 3,
max_date: "2017-02-13 14:24:55",
last_time_entries_checked: null,
account_code: "101200",
partner_id: 12,
account_name: "101200 Account Receivable",
mode: "customers",
},
],
accounts: [
{
account_id: 283,
account_name: "101000 Current Assets",
currency_id: 3,
max_date: "2017-02-16 14:32:04",
last_time_entries_checked: "2017-02-16",
account_code: "101000",
mode: "accounts",
reconciliation_proposition: [
{
account_id: 283,
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-16",
date: "2017-02-16",
total_amount_str: "$ 1,000.00",
partner_id: 8,
account_name: "101000 Current Assets",
name: "BNK1/2017/0006: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 399,
credit: 1000.0,
journal_id: [3, "Bank"],
amount_str: "$ 1,000.00",
debit: 0.0,
account_code: "101000",
ref: "",
already_paid: false,
},
{
account_id: 283,
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-03-18",
date: "2017-02-16",
total_amount_str: "$ 1,000.00",
partner_id: 8,
account_name: "101000 Current Assets",
name: "INV/2017/0006",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 402,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1,000.00",
debit: 1000.0,
account_code: "101000",
ref: "",
already_paid: false,
},
],
},
],
suppliers: [
{
account_id: 284,
partner_name: "Agrolait",
reconciliation_proposition: [
{
account_id: 284,
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-16",
date: "2017-02-16",
total_amount_str: "$ 1,000.00",
partner_id: 8,
account_name: "101000 Current Assets",
name: "BNK1/999: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 999,
credit: 1000.0,
journal_id: [3, "Bank"],
amount_str: "$ 1,000.00",
debit: 0.0,
account_code: "111100",
ref: "",
already_paid: false,
},
{
account_id: 284,
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-03-18",
date: "2017-02-16",
total_amount_str: "$ 1,000.00",
partner_id: 8,
account_name: "101000 Current Assets",
name: "INV/998",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 998,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1,000.00",
debit: 1000.0,
account_code: "111100",
ref: "",
already_paid: false,
},
],
currency_id: 3,
max_date: "2017-02-14 12:36:05",
last_time_entries_checked: null,
account_code: "111100",
partner_id: 8,
account_name: "Account Payable",
mode: "suppliers",
},
{
account_id: 284,
partner_name: "Camptocamp",
reconciliation_proposition: [
{
account_id: 284,
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-16",
date: "2017-02-16",
total_amount_str: "$ 1,000.00",
partner_id: 12,
account_name: "101000 Current Assets",
name: "BNK1/1999: Customer Payment",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 1999,
credit: 1000.0,
journal_id: [3, "Bank"],
amount_str: "$ 1,000.00",
debit: 0.0,
account_code: "111100",
ref: "",
already_paid: false,
},
{
account_id: 284,
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-03-18",
date: "2017-02-16",
total_amount_str: "$ 1,000.00",
partner_id: 12,
account_name: "101000 Current Assets",
name: "INV/1998",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 1998,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1,000.00",
debit: 1000.0,
account_code: "111100",
ref: "",
already_paid: false,
},
],
currency_id: 3,
max_date: "2017-02-14 12:36:05",
last_time_entries_checked: null,
account_code: "111100",
partner_id: 12,
account_name: "Account Payable",
mode: "suppliers",
},
],
},
'["partner",null,"receivable"]': [
{
account_id: 287,
partner_name: "Agrolait",
reconciliation_proposition: [],
currency_id: 3,
max_date: "2017-02-14 12:30:31",
last_time_entries_checked: null,
account_code: "101200",
partner_id: 8,
account_name: "101200 Account Receivable",
mode: "customers",
},
{
account_id: 287,
partner_name: "Camptocamp",
reconciliation_proposition: [],
currency_id: 3,
max_date: "2017-02-13 14:24:55",
last_time_entries_checked: null,
account_code: "101200",
partner_id: 12,
account_name: "101200 Account Receivable",
mode: "customers",
},
],
};
var move_lines_for_manual_reconciliation = {
'[287,8,"",0]': [
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency_str: "10,222.00 €",
currency_id: 1,
date_maturity: "2017-02-08",
date: "2017-02-08",
total_amount_str: "$ 11,000.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0004: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 17,
credit: 11000.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 11,000.00",
debit: 0.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
account_id: [7, "101200 Account Receivable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-09",
date: "2017-02-09",
total_amount_str: "$ 1,000.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0005: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 19,
credit: 1000.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1,000.00",
debit: 0.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-09",
date: "2017-02-09",
total_amount_str: "$ 180.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "BILL/2017/0003: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 21,
credit: 180.0,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 180.00",
debit: 0.0,
account_code: "101200",
ref: "fddfgfdgfdgsdfg",
already_paid: false,
},
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-09",
date: "2017-02-09",
total_amount_str: "$ 90.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0006: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 23,
credit: 90.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 90.00",
debit: 0.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-03-10",
date: "2017-02-08",
total_amount_str: "$ 650.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0012",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 6,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1000.00",
debit: 1000.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-03-10",
date: "2017-02-08",
total_amount_str: "$ 525.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0003",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 9,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 525.00",
debit: 525.0,
account_code: "101200",
ref: "",
already_paid: false,
},
],
'[7,12,"",0]': [
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-08",
date: "2017-02-08",
total_amount_str: "$ 11,000.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0004: Customer Payment",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 17,
credit: 11000.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 11,000.00",
debit: 0.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
account_id: [7, "101200 Account Receivable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-09",
date: "2017-02-09",
total_amount_str: "$ 1,000.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0005: Customer Payment",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 19,
credit: 1000.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1,000.00",
debit: 0.0,
account_code: "101200",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency: 100,
amount_currency_str: "100.00 €",
currency_id: 1,
date_maturity: "2017-02-09",
date: "2017-02-09",
total_amount_str: "$ 170.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0003: Customer Payment",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 21,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 170.00",
debit: 170.0,
account_code: "101200",
ref: "INV fddfgfdgfdgsdfg",
already_paid: false,
},
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency: 100,
amount_currency_str: "100.00 €",
currency_id: 1,
date_maturity: "2017-02-10",
date: "2017-02-10",
total_amount_str: "$ 180.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "BILL/2017/0003: Customer Payment",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 22,
credit: 180.0,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 180.00",
debit: 0.0,
account_code: "101200",
ref: "fddfgfdgfdgsdfg",
already_paid: false,
},
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency: 170,
amount_currency_str: "170.00 €",
currency_id: 1,
date_maturity: "2017-02-09",
date: "2017-02-09",
total_amount_str: "$ 100.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "INV/2017/0003: Customer Payment",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 23,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 100.00",
debit: 100.0,
account_code: "101200",
ref: "INV fddfgfdgfdgsdfg",
already_paid: false,
},
{
account_type: "receivable",
account_id: [287, "101200 Account Receivable"],
amount_currency: 180,
amount_currency_str: "180.00 €",
currency_id: 1,
date_maturity: "2017-02-10",
date: "2017-02-10",
total_amount_str: "$ 100.00",
partner_id: 12,
account_name: "101200 Account Receivable",
name: "BILL/2017/0003: Customer Payment",
partner_name: "Camptocamp",
total_amount_currency_str: "",
id: 24,
credit: 100.0,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 100.00",
debit: 0.0,
account_code: "101200",
ref: "fddfgfdgfdgsdfg",
already_paid: false,
},
],
'[284,8,"",0]': [
{
account_type: "receivable",
account_id: [284, "111100 Account Payable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-08",
date: "2017-02-08",
total_amount_str: "$ 11,000.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0004: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 17,
credit: 11000.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 11,000.00",
debit: 0.0,
account_code: "111100",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
account_id: [284, "111100 Account Payable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-09",
date: "2017-02-09",
total_amount_str: "$ 1,000.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0005: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 19,
credit: 1000.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1,000.00",
debit: 0.0,
account_code: "111100",
ref: "",
already_paid: false,
},
{
account_type: "receivable",
account_id: [284, "111100 Account Payable"],
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-09",
date: "2017-02-09",
total_amount_str: "$ 180.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "BILL/2017/0003: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 21,
credit: 180.0,
journal_id: [2, "Vendor Bills"],
amount_str: "$ 180.00",
debit: 0.0,
account_code: "111100",
ref: "fddfgfdgfdgsdfg",
already_paid: false,
},
],
'[283,null,"",0]': [
{
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-16",
date: "2017-02-16",
total_amount_str: "$ 1,000.00",
partner_id: 8,
account_name: "101000 Current Assets",
name: "BNK1/2017/0006: Customer Payment",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 399,
credit: 1000.0,
journal_id: [3, "Bank"],
amount_str: "$ 1,000.00",
debit: 0.0,
account_code: "101000",
ref: "",
already_paid: false,
},
{
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-03-18",
date: "2017-02-16",
total_amount_str: "$ 1,000.00",
partner_id: 8,
account_name: "101000 Current Assets",
name: "INV/2017/0006",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 402,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1,000.00",
debit: 1000.0,
account_code: "101000",
ref: "",
already_paid: false,
},
],
'[284,12,"",0]': [],
};
var session = {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
};
var options = {
context: {
statement_line_ids: [4],
},
params: {
limitMoveLines: 5,
},
};
Datas.params = {
data: db,
data_preprocess: data_preprocess,
data_widget: data_widget,
mv_lines: mv_lines,
auto_reconciliation: auto_reconciliation,
data_for_manual_reconciliation_widget: data_for_manual_reconciliation_widget,
move_lines_for_manual_reconciliation: move_lines_for_manual_reconciliation,
session: session,
options: options,
};
// This is the main function for this module. Its job is to export (and clone) all data for a test.
Datas.getParams = function () {
return (this.used = $.extend(true, {}, this.params));
};
return Datas;
});
odoo.define("account.reconciliation_tests", function (require) {
"use strict";
var ReconciliationClientAction = require("account.ReconciliationClientAction");
var ReconciliationRenderer = require("account.ReconciliationRenderer");
var demoData = require("account.reconciliation_tests.data");
var testUtils = require("web.test_utils");
var testUtilsDom = require("web.test_utils_dom");
var testUtilsMock = require("web.test_utils_mock");
QUnit.module(
"account",
{
beforeEach: function () {
this.params = demoData.getParams();
testUtils.patch(ReconciliationRenderer.LineRenderer, {
MV_LINE_DEBOUNCE: 0,
});
},
afterEach: function () {
testUtils.unpatch(ReconciliationRenderer.LineRenderer);
},
},
function () {
QUnit.module("Reconciliation");
QUnit.test("Reconciliation basic rendering", async function (assert) {
assert.expect(10);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
assert.hasClass(
widget.$el,
"o_reconciliation_line",
"should instance of widget reconciliation"
);
assert.containsOnce(widget, ".accounting_view", "should have one view");
assert.containsN(
widget,
'[id*="notebook_page_match"]',
2,
"should have 'match_rp' and 'match_other' panel"
);
assert.containsOnce(widget, ".create", "should have 'create' panel");
assert.strictEqual(
widget
.$("thead")
.text()
.replace(/[\n\r\s]+/g, " "),
" 101401 2017-01-01 SAJ/2014/002 and SAJ/2014/003 $ 1,175.00 ",
"should display the line information"
);
assert.ok(
widget.$("caption .o_field_many2one").length,
"should display the many2one with to select a partner"
);
assert.containsN(
clientAction,
'[data-mode="inactive"]',
3,
"should be as 'inactive' mode by default"
);
assert.strictEqual(
widget.$el.data("mode"),
"match_rp",
"the first one should automatically switch to match_rp mode"
);
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
assert.strictEqual(
widget.$el.data("mode"),
"create",
"should switch to 'create' mode"
);
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_match_rp"]')
);
assert.strictEqual(
widget.$el.data("mode"),
"match_rp",
"should switch to 'match_rp' mode"
);
clientAction.destroy();
});
QUnit.test("Reconciliation fields", async function (assert) {
assert.expect(6);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
user_has_group: function (group) {
if (
group === "analytic.group_analytic_tags" ||
group === "analytic.group_analytic_accounting"
) {
return $.when(true);
}
return this._super.apply(this, arguments);
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
assert.strictEqual(
widget.$(".o_input_dropdown input").val(),
"Agrolait",
"the partner many2one should display agrolait"
);
assert.strictEqual(
clientAction.widgets[2].$(".o_input_dropdown input").val(),
"Camptocamp",
"the partner many2one should display Camptocamp"
);
await testUtils.dom.click(widget.$(".accounting_view tfoot td:first"));
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
assert.containsN(
widget,
".create input.o_input",
8,
"create panel should contain 8 fields (account_id, tax_id, journal_id, analytic_account_id, analytic_tag_ids, label, amount, date)"
);
assert.containsN(
widget,
".create .create_account_id .o_required_modifier, .create .create_label .o_required_modifier, .create .create_amount .o_required_modifier",
3,
"account_id, label and amount should be required fields"
);
assert.strictEqual(
widget.$(".create .create_label input").val(),
"SAJ/2014/002 and SAJ/2014/003",
"should use the name of the reconciliation line for the default label value"
);
assert.strictEqual(
widget.$(".create .create_amount input").val(),
"1175.00",
"should have the balance amout as default value for the amout field"
);
clientAction.destroy();
});
QUnit.test("Reconciliation basic data", async function (assert) {
assert.expect(17);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
assert.containsN(
widget,
".match:first .mv_line",
2,
"should display 2 account move lines"
);
assert.strictEqual(
widget
.$(".match:first .mv_line")
.text()
.replace(/[\n\r\s]+/g, " ")
.replace(/[\u200B]/g, ""),
" 101200 2017-02-07 INV/2017/0002 $ 650.00 101200 2017-02-07 INV/2017/0003 $ 525.00 ",
"should display 4 account move lines who contains the account_code, due_date, label and the credit"
);
assert.strictEqual(
widget.$('.match:first .mv_line .cell_right:contains(".")').length,
2,
"should display only the credit account move lines (hide the debit)"
);
await testUtils.dom.click(
clientAction.widgets[1].$(".accounting_view thead td:first")
);
assert.containsN(
clientAction.widgets[1],
".mv_line",
5,
"should display 5 account move lines"
);
assert.strictEqual(
clientAction.widgets[1].$('.mv_line .cell_right:contains(".")')
.length,
3,
"should display only the credit account move lines (hide the debit)"
);
assert.containsN(
clientAction.widgets[1],
".mv_line.already_reconciled",
3,
"should display 3 already reconciled account move lines"
);
assert.strictEqual(
clientAction.widgets[1]
.$(".mv_line")
.text()
.replace(/[\n\r\s]+/g, " ")
.replace(/[\u200B]/g, ""),
" 101401 2017-01-23 ASUSTeK: BNK1/2017/0002: SUPP.OUT/2017/0002 : BILL/2017/0003 $ 376.00 101401 2017-01-23 Agrolait: BNK1/2017/0003: CUST.IN/2017/0001 $ 100.00 111100 2017-02-28 Camptocamp: BILL/2017/0001 $ 10,000.00 101401 2017-01-23 Agrolait: BNK1/2017/0004: CUST.IN/2017/0002 : INV/2017/0003 $ 525.50 101200 2017-02-07 Agrolait: INV/2017/0002 $ 650.00 ",
"should display 4 account move lines who contains the account_code, due_date, label and the credit"
);
assert.strictEqual(
clientAction.widgets[1].$('.mv_line .cell_left:contains(".")')
.length,
2,
"should display only 2 debit account move lines"
);
// Load more
assert.ok(
clientAction.widgets[1].$(".match:first div.load-more a:visible")
.length,
"should display the 'load more' button"
);
assert.equal(
clientAction.widgets[1].$(".match:first div.load-more span").text(),
3,
"should display 3 items remaining"
);
await testUtils.dom.click(
clientAction.widgets[1].$(".match:first div.load-more a")
);
assert.containsN(
clientAction.widgets[1],
".mv_line",
8,
"should load 3 more records"
);
assert.notOk(
clientAction.widgets[1].$(".match:first div.load-more a:visible")
.length,
"should not display the 'load more' button anymore"
);
assert.ok(
clientAction.widgets[0].$("caption button.btn-secondary:visible")
.length,
"should display the secondary 'Validate' button"
);
assert.equal(
clientAction.widgets[1].$("caption button:disabled:visible").length,
1,
"button should be disabled"
);
assert.ok(
clientAction.widgets[2].$("caption button.btn-primary:visible")
.length,
"should display the primary 'Validate' button"
);
await testUtils.dom.click(
clientAction.widgets[3].$(".accounting_view thead td:first")
);
assert.strictEqual(
clientAction.widgets[3].$el.data("mode"),
"create",
"should switch to 'create' mode instead of 'match_rp' mode when 'match_rp' mode is empty"
);
// Open the first line
await testUtils.dom.click(widget.$(".accounting_view thead td:first"));
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_match_rp"]')
);
// Select propositions
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
// Await testUtils.dom.click(widget.$('caption')); //why is it inactive?
testUtils.mock.intercept(clientAction, "call_service", function (
event
) {
if (event.data.args[1].method == "process_bank_statement_line") {
assert.deepEqual(
event.data.args[1].args,
[
[5],
[
{
partner_id: 8,
counterpart_aml_dicts: [
{
counterpart_aml_id: 109,
credit: 650,
debit: 0,
name: "INV/2017/0002",
analytic_tag_ids: [[6, null, []]],
},
{
counterpart_aml_id: 112,
credit: 525,
debit: 0,
name: "INV/2017/0003",
analytic_tag_ids: [[6, null, []]],
},
],
payment_aml_ids: [],
new_aml_dicts: [],
to_check: false,
},
],
],
"Should call process_bank_statement_line with args"
);
var def = testUtils.makeTestPromise();
def.abort = function () {};
event.data.callback(def);
}
});
// Click on reconcile button
await testUtils.dom.click(widget.$(".o_reconcile:visible"));
clientAction.destroy();
});
QUnit.test("Reconciliation validate without proposition", async function (
assert
) {
assert.expect(1);
// Test added to prevent this issue happening again: https://github.com/odoo/odoo/commit/3549688b21eb65e16b9c3f2b6462eb8d8b52cd47
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
// Ensure that when we validate a line without any selection, it is the same
// as when we manually create a line with the line.balance and that only one
// line is send back to server.
testUtils.mock.intercept(clientAction, "call_service", function (
event
) {
assert.deepEqual(
event.data.args[1].args,
[
[5],
[
{
partner_id: 8,
to_check: false,
counterpart_aml_dicts: [],
payment_aml_ids: [],
to_check: false,
new_aml_dicts: [
{
account_id: 287,
credit: 1175,
debit: 0,
name: "SAJ/2014/002 and SAJ/2014/003",
analytic_tag_ids: [[6, null, []]],
},
],
},
],
],
"Should call process_bank_statement_line with ids"
);
var def = testUtils.makeTestPromise();
def.abort = function () {};
event.data.callback(def);
});
// Click on validate button
await testUtils.dom.click(widget.$("button.o_validate:not(:hidden)"));
clientAction.destroy();
});
QUnit.test("Reconciliation validate with proposition", async function (
assert
) {
assert.expect(1);
// Test added to check this functionality: https://github.com/odoo/odoo/commit/2f3b469dee6f18cbccce1cdf2a81cfe57960c533
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
// Add a line as proposition
// open the first line
await testUtils.dom.click(widget.$(".accounting_view thead td:first"), {
allowInvisible: true,
});
await testUtils.nextTick();
// Select propositions
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first"),
{allowInvisible: true}
);
await testUtils.nextTick();
// Ensure that when we validate a line with propositions and that there is a remaining balance
// We also create a line which is the open balance.
testUtils.mock.intercept(clientAction, "call_service", function (
event
) {
assert.deepEqual(
event.data.args[1].args,
[
[5],
[
{
partner_id: 8,
to_check: false,
counterpart_aml_dicts: [
{
counterpart_aml_id: 109,
credit: 650,
debit: 0,
name: "INV/2017/0002",
analytic_tag_ids: [[6, null, []]],
},
],
payment_aml_ids: [],
new_aml_dicts: [
{
account_id: 287,
credit: 525,
debit: 0,
name:
"SAJ/2014/002 and SAJ/2014/003 : Open balance",
},
],
},
],
],
"Should call process_bank_statement_line with ids"
);
var def = testUtils.makeTestPromise();
def.abort = function () {};
event.data.callback(def);
});
// Click on validate button
await testUtils.dom.click(widget.$("button.o_validate:not(:hidden)"));
clientAction.destroy();
});
QUnit.test("Reconciliation partial [REQUIRE FOCUS]", async function (
assert
) {
assert.expect(8);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
mockRPC: function (route, args) {
console.log(args.method);
if (args.method === "process_bank_statement_line") {
var lines = args.args["1"];
console.log(args.arsg);
assert.deepEqual(
args.args,
[
[6],
[
{
partner_id:
lines.length == 1
? lines[0].partner_id
: false,
counterpart_aml_dicts: [
{
analytic_tag_ids: [[6, null, []]],
counterpart_aml_id: 114,
credit: 0,
debit: 32.58,
name: "BILL/2017/0001",
},
],
payment_aml_ids: [],
new_aml_dicts: [],
to_check: false,
},
],
],
"should call process_bank_statement_line with partial reconcile values"
);
}
return this._super(route, args);
},
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
assert.equal(
widget.$(".cell_right .edit_amount").length,
1,
"should display the edition pencil"
);
widget = clientAction.widgets[1];
await testUtils.dom.click(widget.$(".accounting_view thead td:first"));
assert.strictEqual(
widget.$(
".match:first .mv_line[data-line-id=114] .cell_account_code:first()"
).length,
1,
"Should have line"
);
await testUtils.dom.click(
widget.$(
".match:first .mv_line[data-line-id=114] .cell_account_code"
)
);
assert.equal(
widget.$(".accounting_view tbody .cell_left .edit_amount").length,
1,
"should display the edition pencil"
);
// The partner has been set automatically, remove it.
await testUtils.dom.click(widget.$(".o_input_dropdown input"));
await testUtils.fields.editAndTrigger(
widget.$(".o_input_dropdown input"),
"",
["keyup", "blur"]
);
assert.equal(
clientAction.widgets[1].$("caption button:disabled:visible").length,
1,
"button should be disabled"
);
await testUtils.dom.click(
widget.$(".accounting_view .cell_left .edit_amount")
);
assert.strictEqual(
widget.$(
".accounting_view .cell_left .edit_amount_input:not(.d-none)"
).length,
1,
"should display the input field to edit amount"
);
// Edit amount
await testUtils.fields.editAndTrigger(
widget.$(
".accounting_view .cell_left .edit_amount_input:not(.d-none)"
),
"32.58",
["change", "blur"]
);
assert.strictEqual(
widget
.$(".accounting_view .cell_left .line_amount")
.text()
.replace(/[\n\r\s]+/g, " "),
" $ 10000.00 $ 32.58 ",
"should display previous amount and new amount"
);
assert.strictEqual(
widget.$("button.btn-primary:visible").length,
1,
"should display the reconcile button"
);
await testUtils.dom.click(widget.$("button.btn-primary:visible"));
clientAction.destroy();
});
QUnit.test("Reconciliation currencies", async function (assert) {
assert.expect(2);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: this.params.session,
translateParameters: {
date_format: "%m/%d/%Y",
direction: "ltr",
name: "English",
thousands_sep: ",",
time_format: "%H:%M:%S",
decimal_point: ".",
id: 1,
grouping: [3, 0],
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
assert.strictEqual(
clientAction
.$(
".accounting_view tfoot .cell_right, .accounting_view tfoot .cell_left"
)
.text()
.replace(/[\n\r\s]+/g, " "),
"$ 1,175.00$ 32.58$ 2,000.00",
"should display the different amounts with the currency"
);
// Await testUtils.dom.click(widget.$('.accounting_view thead .mv_line td:first'));
assert.strictEqual(
clientAction
.$(".accounting_view tbody")
.text()
.replace(/[\n\r\s]+/g, " ")
.replace(/[\u200B]/g, ""),
" 101200 2017-02-07 INV/2017/0012 $ 650.00 ",
"should display the created reconciliation line with the currency"
);
clientAction.destroy();
});
QUnit.test("Reconciliation change partner", async function (assert) {
assert.expect(17);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
archs: {
"res.partner,false,list":
'',
"res.partner,false,search":
'' +
'' +
"",
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
assert.strictEqual(
widget.$(".o_input_dropdown input").val(),
"Agrolait",
"the partner many2one should display agrolait"
);
assert.containsN(
widget,
".match:first table tr",
2,
"agrolait should have 2 propositions for reconciliation"
);
// Adding the two propositions
// This is in order to try that after changing partner the propositions are emptied
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
assert.containsN(
widget,
".accounting_view tbody tr",
2,
"Both proposition should be selected"
);
// Similate changing partner to one that does not have propositions to see if create mode is open after
await testUtils.dom.click(widget.$(".o_input_dropdown input"));
$(".ui-autocomplete .ui-menu-item a:contains(partner 1)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
clientAction._onAction({
target: widget,
name: "change_partner",
data: {data: {display_name: "partner 1", id: 1}},
stopped: false,
});
await testUtils.nextTick();
assert.strictEqual(
widget.$(".o_input_dropdown input").val(),
"partner 1",
"the partner many2one should display partner 1"
);
assert.containsNone(
widget,
".match:first table tr.mv_line",
"partner 1 should have 0 propositions for reconciliation"
);
assert.strictEqual(
widget.$el.data("mode"),
"create",
"widget should be in create mode"
);
// Simulate changing partner
await testUtils.dom.clickFirst(widget.$(".o_input_dropdown input"));
$(".ui-autocomplete .ui-menu-item a:contains(Camptocamp)")
.trigger("mouseenter")
.trigger("click");
clientAction._onAction({
target: widget,
name: "change_partner",
data: {data: {display_name: "Camptocamp", id: 12}},
stopped: false,
});
await testUtils.nextTick();
assert.strictEqual(
widget.$(".o_input_dropdown input").val(),
"Camptocamp",
"the partner many2one should display Camptocamp"
);
assert.containsN(
widget,
".match:first table tr.mv_line",
3,
"camptocamp should have 3 propositions for reconciliation"
);
// Simulate changing partner with SelectCreateDialog
widget = clientAction.widgets[1];
assert.strictEqual(
$(".modal").length,
0,
"shouldn't have any opened modal"
);
await testUtils.dom.click(widget.$(".o_input_dropdown input"));
$(".ui-autocomplete .ui-menu-item a:contains(Search More):eq(1)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
assert.strictEqual(
$(".modal").length,
1,
"should open a SelectCreateDialog"
);
await testUtils.dom.click(
$(".modal table.o_list_table td:contains(Camptocamp)")
);
assert.strictEqual(
widget.$(".o_input_dropdown input").val(),
"Camptocamp",
"the partner many2one should display Camptocamp"
);
widget = clientAction.widgets[2];
await testUtils.dom.click(widget.$(".accounting_view thead td:first"));
await testUtils.dom.click(
widget.$(".accounting_view .mv_line .cell_label")
);
assert.strictEqual(
widget.$(".o_input_dropdown input").val(),
"Camptocamp",
"the partner many2one should display agrolait"
);
assert.containsN(
widget,
".match:first table tr",
3,
"Camptocamp should have 3 propositions for reconciliation"
);
assert.notOk(
widget.$(".match:first div.load-more a:visible").length,
"should not display the load more button"
);
// Simulate remove partner
await testUtils.dom.click(widget.$(".o_input_dropdown input"));
await testUtils.fields.editAndTrigger(
widget.$(".o_input_dropdown input"),
"",
["keyup", "blur"]
);
assert.strictEqual(
widget.$(".o_input_dropdown input").val(),
"",
"the partner many2one should be empty"
);
assert.containsN(
widget,
".match:first table tr.mv_line",
5,
"should have 5 propositions for reconciliation if partner is false"
);
assert.ok(
widget.$(".match:first div.load-more a:visible").length,
"should display the load more button"
);
clientAction.destroy();
});
QUnit.test("Reconciliation create line", async function (assert) {
assert.expect(23);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
assert.strictEqual(
clientAction
.$(
".accounting_view tfoot .cell_right, .accounting_view tfoot .cell_left"
)
.text()
.replace(/[$, ]+/g, ""),
" 1175.00 32.58 2000.00",
"should display the open balance values"
);
var widget = clientAction.widgets[0];
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_label").text(),
"Open balance",
"should display 'Open Balance' line with the rest to reconcile"
);
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
await testUtils.dom.click(widget.$(".create .create_account_id input"));
$(
".ui-autocomplete .ui-menu-item a:contains(101200 Account Receivable)"
)
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
assert.notOk(
widget.$(".accounting_view tfoot .cell_label").text(),
"should not display 'Open Balance' line because the rest to reconcile is null"
);
assert.containsOnce(
widget,
".accounting_view tbody tr",
"should have only the created reconcile line"
);
assert.strictEqual(
widget
.$(".accounting_view tbody tr")
.text()
.replace(/[\n\r\s$,]+/g, " ")
.replace(/[\u200B]/g, ""),
" 101200 New SAJ/2014/002 and SAJ/2014/003 1175.00 ",
"the new line should have the selected account, name and amout"
);
assert.ok(
widget.$("caption button.btn-primary:visible").length,
"should display the 'Reconcile' button"
);
testUtils.mock.intercept(clientAction, "do_action", function (event) {
assert.strictEqual(
JSON.stringify(event.data.action),
'{"type":"ir.actions.act_window","res_model":"account.reconcile.model","views":[[false,"form"]],"target":"current"}',
"should open the reconcile model form view"
);
});
await testUtils.dom.click(widget.$(".create .reconcile_model_create"), {
allowInvisible: true,
});
testUtils.mock.intercept(clientAction, "do_action", function (event) {
assert.strictEqual(
JSON.stringify(event.data.action),
'{"type":"ir.actions.act_window","res_model":"account.reconcile.model","views":[[false,"list"],[false,"form"]],"view_mode":"list","target":"current"}',
"should open the reconcile model list view"
);
});
await testUtils.dom.click(widget.$(".create .reconcile_model_edit"), {
allowInvisible: true,
});
await testUtils.fields.editInput(
widget.$(".create .create_amount input"),
"1100.00"
);
assert.strictEqual(
widget
.$(".accounting_view tbody .cell_right")
.text()
.trim()
.replace(/[\n\r\s\u00a0]+/g, " "),
"$ 1100.00",
"should display the value 1100.00 in right column"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_right").text(),
"$ 75.00",
"should display 'Open Balance' line because the rest to reconcile is 75.00"
);
assert.containsOnce(
widget,
".accounting_view tbody tr",
"should have ever only the created reconcile line"
);
assert.strictEqual(
widget
.$(".accounting_view tbody tr")
.text()
.replace(/[\n\r\s$,]+/g, " ")
.replace(/[\u200B]/g, ""),
" 101200 New SAJ/2014/002 and SAJ/2014/003 1100.00 ",
"the new line should be update the amout"
);
assert.ok(
widget.$("caption button.btn-secondary:visible").length,
"should display the 'validate' button"
);
await testUtils.dom.click(widget.$(".create .add_line"), {
allowInvisible: true,
});
await testUtils.fields.editInput(
widget.$(".create .create_amount input"),
"-100"
);
await testUtils.dom.click(widget.$(".create .create_account_id input"));
$(".ui-autocomplete .ui-menu-item a:contains(101000 Current Assets)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
await testUtils.fields.editInput(
widget.$(".create .create_label input"),
"test0"
);
assert.strictEqual(
widget
.$(".accounting_view tbody .cell_left:last")
.text()
.trim()
.replace(/[\n\r\s\u00a0]+/g, " "),
"$ 100.00",
"should display the value 100.00 in left column"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_label").text(),
"Open balance",
"should display 'Open Balance'"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_right").text(),
"$ 175.00",
"should display 'Open Balance' line because the rest to reconcile is 175.00"
);
assert.containsN(
widget,
".accounting_view tbody tr",
2,
"should have 2 created reconcile lines"
);
assert.strictEqual(
widget
.$(".accounting_view tbody tr:eq(1)")
.text()
.replace(/[\n\r\s$,]+/g, " ")
.replace(/[\u200B]/g, ""),
" 101000 New test0 100.00 ",
"the new line should have the selected account, name and amout"
);
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
assert.strictEqual(
widget.$(".create .create_amount input").val(),
"175.00",
"should have '175.00' as default amount value"
);
await testUtils.fields.editInput(
widget.$(".create .create_amount input"),
"200"
);
widget.$(".create .create_account_id input").trigger("click");
$(".ui-autocomplete .ui-menu-item a:contains(101000 Current Assets)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
await testUtils.fields.editInput(
widget.$(".create .create_label input"),
"test1"
);
assert.strictEqual(
widget
.$(".accounting_view tbody .cell_right:last")
.text()
.trim()
.replace(/[\n\r\s\u00a0]+/g, " "),
"$ 200.00",
"should display the value 200.00 in left column"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_label").text(),
"Open balance",
"should display 'Open balance'"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_left").text(),
"$ 25.00",
"should display 'Open balance' with 25.00 in left column"
);
assert.containsN(
widget,
".accounting_view tbody tr",
3,
"should have 3 created reconcile lines"
);
clientAction.destroy();
});
QUnit.test("Reconciliation create line (many2one test)", async function (
assert
) {
assert.expect(5);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
var def = testUtils.makeTestPromise();
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.account,false,list":
'',
"account.account,false,search":
'',
"account.bank.statement.line,false,search":
'',
},
mockRPC: function (route, args) {
if (args.method === "name_get") {
return def.then(this._super.bind(this, route, args));
}
return this._super(route, args);
},
});
await clientAction.prependTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
// Open the first line in write-off mode
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
// Select an account with the many2one (drop down)
await testUtils.dom.click(widget.$(".create .create_account_id input"));
$(".ui-autocomplete .ui-menu-item a:contains(101200)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
assert.strictEqual(
widget.$(".create .create_account_id input").val(),
"101200 Account Receivable",
"Display the selected account"
);
assert.strictEqual(
widget
.$("tbody:first .cell_account_code")
.text()
.replace(/[\u200B]/g, ""),
"101200",
"Display the code of the selected account"
);
// Use the many2one select dialog to change the account
await testUtils.dom.click(widget.$(".create .create_account_id input"));
$(".ui-autocomplete .ui-menu-item a:contains(Search)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
// Select the account who does not appear in the drop drown
await testUtils.dom.click($(".modal tr.o_data_row:contains(502)"));
assert.strictEqual(
widget.$(".create .create_account_id input").val(),
"101200 Account Receivable",
"Selected account does not change"
);
// Wait the name_get to render the changes
def.resolve();
await testUtils.nextTick();
assert.strictEqual(
widget.$(".create .create_account_id input").val(),
"502 Account",
"Display the selected account"
);
assert.strictEqual(
widget
.$("tbody:first .cell_account_code")
.text()
.replace(/[\u200B]/g, ""),
"502",
"Display the code of the selected account"
);
clientAction.destroy();
});
QUnit.test("Reconciliation create line with taxes", async function (
assert
) {
assert.expect(13);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
await testUtils.dom.click(widget.$(".create .create_account_id input"));
$(".ui-autocomplete .ui-menu-item a:contains(101000 Current Assets)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
await testUtils.fields.editInput(
widget.$(".create .create_label input"),
"test1"
);
await testUtils.fields.editInput(
widget.$(".create .create_amount input"),
"1100"
);
assert.strictEqual(
widget
.$(".accounting_view tbody .cell_right:last")
.text()
.trim()
.replace(/[\n\r\s\u00a0]+/g, " "),
"$ 1100.00",
"should display the value 1100.00 in left column"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_label").text(),
"Open balance",
"should display 'Open Balance'"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_right").text(),
"$\u00a075.00",
"should display 'Open Balance' with 75.00 in right column"
);
assert.containsOnce(
widget,
".accounting_view tbody tr",
"should have 1 created reconcile lines"
);
await testUtils.dom.click(widget.$(".create .create_tax_id input"));
$(".ui-autocomplete .ui-menu-item a:contains(10.00%)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
assert.strictEqual(
widget
.$(".accounting_view tbody .cell_right")
.text()
.trim()
.replace(/[\n\r\s\u00a0]+/g, " "),
"$ 1000.00 $ 100.00",
"should have 2 created reconcile lines with right column values"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_label").text(),
"Open balance",
"should display 'Open Balance'"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_right").text(),
"$\u00a075.00",
"should display 'Open Balance' with 75.00 in right column"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_left").text(),
"",
"should display 'Open Balance' without any value in left column"
);
assert.containsN(
widget,
".accounting_view tbody tr",
2,
"should have 2 created reconcile lines"
);
await testUtils.dom.click(widget.$('[name="tax_ids"] a.o_delete'));
widget
.$(".create .create_tax_id input")
.val("")
.trigger("keyup")
.trigger("blur");
await testUtils.dom.click(widget.$(".create .create_tax_id input"));
$(".ui-autocomplete .ui-menu-item a:contains(20.00%)")
.trigger("mouseenter")
.trigger("click");
await testUtils.nextTick();
assert.strictEqual(
widget
.$(".accounting_view tbody .cell_right")
.text()
.trim()
.replace(/[\n\r\s\u00a0]+/g, " "),
"$ 1100.00 $ 220.00",
"should have 2 created reconcile lines with right column values"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_label").text(),
"Open balance",
"should display 'Open balance'"
);
assert.strictEqual(
widget.$(".accounting_view tfoot .cell_left").text(),
"$\u00a0145.00",
"should display 'Open balance' with 145.00 in right column"
);
assert.containsN(
widget,
".accounting_view tbody tr",
2,
"should have 2 created reconcile lines"
);
clientAction.destroy();
});
QUnit.test(
"Reconciliation create line from reconciliation model",
async function (assert) {
assert.expect(6);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
await testUtils.dom.click(
widget.$(".create .quick_add button:contains(ATOS)")
);
assert.strictEqual(
widget
.$(
".accounting_view tbody .cell_label, .accounting_view tbody .cell_right"
)
.text()
.replace(/[\n\r\s$,]+/g, " "),
" ATOS Banque 1145.63 ATOS Banque Tax 20.00% 229.13 ATOS Frais 26.78 ATOS Frais Tax 10.00% include 2.68 ",
"should display 4 lines"
);
assert.strictEqual(
widget
.$(
".accounting_view tfoot .cell_label, .accounting_view tfoot .cell_left"
)
.text()
.replace(/[\n\r\s$,]+/g, ""),
"Openbalance229.22",
"should display the 'Open balance' line with value in left column"
);
await testUtils.fields.editAndTrigger(
widget.$(".create .create_amount input"),
"100",
["input"]
);
assert.strictEqual(
widget
.$(".accounting_view tbody")
.text()
.replace(/[\n\r\s$,]+/g, " ")
.replace(/[\u200B]/g, ""),
" 101120 New ATOS Banque 1145.63 101120 New ATOS Banque Tax 20.00% 229.13 101130 New ATOS Frais 90.91 101300 New ATOS Frais Tax 10.00% include 9.09 ",
"should update the value of the 2 lines (because the line + its tax must have 100% of the value)"
);
assert.strictEqual(
widget
.$(
".accounting_view tfoot .cell_label, .accounting_view tfoot .cell_left"
)
.text()
.replace(/[\n\r\s$,]+/g, ""),
"Openbalance299.76",
"should change the 'Open balance' line because the 20.00% tax is not an include tax"
);
await testUtils.dom.click(
widget.$(".accounting_view tbody .cell_account_code:first")
);
await testUtils.dom.click(
widget.$(".accounting_view tbody .cell_label:first")
);
assert.strictEqual(
widget
.$(".accounting_view tbody")
.text()
.replace(/[\n\r\s$,]+/g, " "),
"",
"should removed every line"
);
await testUtils.dom.click(
widget.$(".create .quick_add button:contains(Double)")
);
assert.strictEqual(
widget
.$(".accounting_view tbody")
.text()
.replace(/[\n\r\s$,]+/g, " ")
.replace(/[\u200B]/g, ""),
" 101120 New Double Banque 1145.63 101130 New Double Frais 29.37 ",
"should have a sum of reconciliation proposition amounts equal to the line amount"
);
clientAction.destroy();
}
);
QUnit.test(
"Reconciliation fetch correct reconciliation models",
async function (assert) {
assert.expect(1);
testUtilsMock.patch(this.params.options.context, {
active_model: "account.journal", // On account dashboard, click "Reconcile" on a journal
active_ids: [1, 2], // Active journals
company_ids: [3, 4], // Active companies
});
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.addMockEnvironment(clientAction, {
data: this.params.data,
mockRPC: async function (route, args) {
if (
args.model === "account.reconcile.model" &&
args.method === "search_read"
) {
assert.deepEqual(
args.kwargs.domain,
[
["company_id", "in", [3, 4]],
"|",
["match_journal_ids", "=", false],
["match_journal_ids", "in", [1, 2]],
],
"The domain to get reconcile models should contain the right fields and values"
);
}
return this._super.apply(this, arguments);
},
});
clientAction.appendTo($("#qunit-fixture"));
testUtilsMock.unpatch(this.params.options.context);
clientAction.destroy();
}
);
QUnit.test("Reconciliation manual", async function (assert) {
assert.expect(13);
var clientAction = new ReconciliationClientAction.ManualAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: this.params.session,
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
assert.strictEqual(
clientAction
.$(".accounting_view:first thead")
.text()
.replace(/[\n\r\s]+/g, " "),
" 101000 Current AssetsLast Reconciliation: 2017-02-16 101000 ",
"should display the account as title"
);
assert.strictEqual(
clientAction.$(".o_reconciliation_line:first").data("mode"),
"inactive",
"should be in 'inactive' mode because no line to displayed and the balance amount is null"
);
assert.containsN(
clientAction,
".accounting_view:first tbody tr",
2,
"should have 2 propositions"
);
assert.containsOnce(
clientAction,
".accounting_view:first .o_reconcile:visible",
"should display the reconcile button"
);
await testUtils.dom.click(
clientAction.$(".accounting_view:first .o_reconcile:visible")
);
assert.strictEqual(
clientAction
.$(".accounting_view:first thead")
.text()
.replace(/[\n\r\s]+/g, " "),
" 101200 Account Receivable 101200 ",
"should display the account and the account code as title"
);
assert.strictEqual(
clientAction
.$(
".o_reconciliation_line:first .match:first tr:first .cell_right"
)
.text()
.trim()
.replace(/[\n\r\s\u00a0]+/g, " "),
"$ 11,000.00",
"sould display the line in $"
);
assert.strictEqual(
clientAction
.$(
".o_reconciliation_line:first .match:first tr:first .cell_right .o_multi_currency"
)
.data("content"),
"10,222.00 €",
"sould display the monetary information in €"
);
assert.containsOnce(
clientAction,
".accounting_view:first .o_no_valid:visible",
"should display the skip button"
);
await testUtils.dom.click(
clientAction.$(".o_reconciliation_line:eq(1) .accounting_view")
);
await testUtils.dom.click(
clientAction.$(".accounting_view:eq(1) thead td:first")
);
// Debugger
await testUtils.dom.click(
clientAction.$(
'.o_reconciliation_line:eq(1) [data-line-id="21"] .cell_label'
)
);
await testUtils.dom.click(
clientAction.$(
'.o_reconciliation_line:eq(1) [data-line-id="22"] .cell_label'
)
);
assert.strictEqual(
clientAction.$(".o_reconciliation_line:eq(1) tfoot tr").length,
0,
"should not display the 'Write-off' line because the balance is null in Euro"
);
assert.strictEqual(
clientAction.$(".o_reconciliation_line:eq(1) .o_reconcile:visible")
.length,
1,
"should display 'Reconcile' button in green"
);
await testUtils.dom.click(
clientAction.$(".o_reconciliation_line:eq(1) .o_reconcile:visible")
);
assert.containsOnce(
clientAction,
'.o_reconciliation_line[data-mode!="inactive"]',
"should have only one line open"
);
await testUtils.dom.click(
clientAction.$(
'.o_reconciliation_line:eq(1) [data-line-id="23"] .cell_label'
)
);
await testUtils.dom.click(
clientAction.$(
'.o_reconciliation_line:eq(1) [data-line-id="24"] .cell_label'
)
);
assert.strictEqual(
clientAction.$(".o_reconciliation_line:eq(1) tfoot tr").length,
1,
"should display the 'Write-off' line because the balance is not null in Euro"
);
assert.strictEqual(
clientAction.$(".o_reconciliation_line:eq(1) .o_validate:visible")
.length,
1,
"should display 'Reconcile' button"
);
clientAction.destroy();
});
QUnit.test(
"Reconciliation: Payment < inv1 + inv2(partial)",
async function (assert) {
assert.expect(3);
/*
* One payment: $1175
* Two Invoices
* The first invoice will be fully reconciled $650
* The second invoice will be partially paid with the rest of the payment $999
*/
// modify the second line that is already in db to put it at $999
var indexModif = _.findIndex(
this.params.mv_lines['[5,"",0]'],
function (line) {
return line.id === 112;
}
);
this.params.mv_lines['[5,"",0]'][indexModif] = {
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 999.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0003",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 112,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 999.00",
debit: 999.0,
account_code: "101200",
ref: "",
already_paid: false,
};
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
mockRPC: function (route, args) {
if (args.method === "process_bank_statement_line") {
assert.deepEqual(
args.args,
[
[5], // Id of the bank statement line
[
{
counterpart_aml_dicts: [
{
name: "INV/2017/0002",
debit: 0,
credit: 650,
analytic_tag_ids: [
[6, null, []],
],
counterpart_aml_id: 109,
},
{
name: "INV/2017/0003",
debit: 0,
credit: 525,
analytic_tag_ids: [
[6, null, []],
],
counterpart_aml_id: 112,
},
],
payment_aml_ids: [],
partner_id: 8,
to_check: false,
new_aml_dicts: [],
},
],
],
"should call process_bank_statement_line with partial reconcile values"
);
}
return this._super(route, args);
},
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
// The first reconciliation "line" is where it happens
var widget = clientAction.widgets[0];
// Add first invoice to reconcile fully
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
assert.ok(
widget.$(".cell_right .edit_amount").length,
"should display the pencil to edit amount"
);
// Add second invoice to reconcile partially
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
// Edit amount on last invoice
await testUtils.dom.click(widget.$(".edit_amount:last()"));
await testUtils.fields.editAndTrigger(
widget.$(".edit_amount_input:last()"),
"525",
["blur"]
);
var $buttonReconcile = widget.$("button.o_reconcile:not(hidden)");
assert.equal(
$buttonReconcile.length,
1,
"The reconcile button must be visible"
);
await testUtils.dom.click($buttonReconcile);
clientAction.destroy();
}
);
QUnit.test("Reconciliation: payment and 2 partials", async function (
assert
) {
assert.expect(6);
/*
* One payment: $1175
* Two Invoices as Inv1 = 1200; Inv2 = 1200:
* Payment < Inv1 AND Payment < Inv2
* No partial reconcile is possible, as a write-off of 1225 is necessary
*/
// modify the invoice line to have their amount > payment
var indexInv1 = _.findIndex(this.params.mv_lines['[5,"",0]'], function (
line
) {
return line.id === 109;
});
this.params.mv_lines['[5,"",0]'][indexInv1] = {
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 1200.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0002",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 109,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1200.00",
debit: 1200.0,
account_code: "101200",
ref: "",
already_paid: false,
};
var indexInv2 = _.findIndex(this.params.mv_lines['[5,"",0]'], function (
line
) {
return line.id === 112;
});
this.params.mv_lines['[5,"",0]'][indexInv2] = {
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 1200.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0003",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 112,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1200.00",
debit: 1200.0,
account_code: "101200",
ref: "",
already_paid: false,
};
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
mockRPC: function (route, args) {
if (args.method === "process_bank_statement_line") {
assert.deepEqual(
args.args,
[
[5], // Id of the bank statement line
[
{
counterpart_aml_dicts: [
{
name: "INV/2017/0002",
debit: 0,
credit: 1200,
analytic_tag_ids: [[6, null, []]],
counterpart_aml_id: 109,
},
{
name: "INV/2017/0003",
debit: 0,
credit: 1200,
analytic_tag_ids: [[6, null, []]],
counterpart_aml_id: 112,
},
],
payment_aml_ids: [],
partner_id: 8,
to_check: false,
new_aml_dicts: [
{
account_id: 282,
credit: 0,
debit: 1225,
analytic_tag_ids: [[6, null, []]],
name:
"SAJ/2014/002 and SAJ/2014/003",
},
],
},
],
],
"should call process_bank_statement_line with new aml dict reconcile values"
);
}
return this._super(route, args);
},
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
// The first reconciliation "line" is where it happens
var widget = clientAction.widgets[0];
// Add first invoice
// There should be the opportunity to reconcile partially
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
assert.ok(
widget.$(".cell_right .edit_amount").length,
"should display the pencil to edit amount"
);
// Add second invoice
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
assert.ok(
widget.$(".cell_right .edit_amount").length,
"should display the pencil to edit amount"
);
var writeOffCreate = widget.$("div.create");
assert.equal(
writeOffCreate.length,
1,
"A write-off creation should be present"
);
assert.equal(
writeOffCreate.find("input[name=amount]").val(),
-1225,
"The right amount should be proposed for the write-off"
);
await testUtils.dom.click(
writeOffCreate.find(
".create_account_id input.ui-autocomplete-input"
)
);
await testUtils.dom.click($("ul.ui-autocomplete li a:first"));
var $buttonReconcile = widget.$("button.o_reconcile:not(hidden)");
assert.equal(
$buttonReconcile.length,
1,
"The reconcile button must be visible"
);
await testUtils.dom.click($buttonReconcile);
clientAction.destroy();
});
QUnit.test(
"Reconciliation: partial payment of 2 invoices with one payment [REQUIRE FOCUS]",
async function (assert) {
assert.expect(4);
/*
* One payment: $1175
* Two Invoices as Inv1 = 1200; Inv2 = 1200:
* Payment < Inv1 AND Payment < Inv2
* Assign 500 to inv1 and 675 to inv2
*/
// modify the invoice line to have their amount > payment
var indexInv1 = _.findIndex(
this.params.mv_lines['[5,"",0]'],
function (line) {
return line.id === 109;
}
);
this.params.mv_lines['[5,"",0]'][indexInv1] = {
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 1200.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0002",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 109,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1200.00",
debit: 1200.0,
account_code: "101200",
ref: "",
already_paid: false,
};
var indexInv2 = _.findIndex(
this.params.mv_lines['[5,"",0]'],
function (line) {
return line.id === 112;
}
);
this.params.mv_lines['[5,"",0]'][indexInv2] = {
account_type: "receivable",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-02-07",
date: "2017-01-08",
total_amount_str: "$ 1200.00",
partner_id: 8,
account_name: "101200 Account Receivable",
name: "INV/2017/0003",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 112,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 1200.00",
debit: 1200.0,
account_code: "101200",
ref: "",
already_paid: false,
};
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
mockRPC: function (route, args) {
if (args.method === "process_bank_statement_line") {
assert.deepEqual(
args.args,
[
[5], // Id of the bank statement line
[
{
counterpart_aml_dicts: [
{
name: "INV/2017/0002",
debit: 0,
credit: 500,
analytic_tag_ids: [
[6, null, []],
],
counterpart_aml_id: 109,
},
{
name: "INV/2017/0003",
debit: 0,
credit: 675,
analytic_tag_ids: [
[6, null, []],
],
counterpart_aml_id: 112,
},
],
payment_aml_ids: [],
partner_id: 8,
to_check: false,
new_aml_dicts: [],
},
],
],
"should call process_bank_statement_line with correct counterpart_aml_dicts"
);
}
return this._super(route, args);
},
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
// The first reconciliation "line" is where it happens
var widget = clientAction.widgets[0];
// Add first invoice
// There should be the opportunity to reconcile partially
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
assert.ok(
widget.$(".cell_right .edit_amount").length,
"should display the pencil to edit amount"
);
// Add second invoice
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
assert.ok(
widget.$(".cell_right .edit_amount").length,
"should display the pencil to edit amount"
);
// Edit invoice first amount
await testUtils.dom.click(widget.$(".edit_amount:first()"));
await testUtils.fields.editAndTrigger(
widget.$(".edit_amount_input:first()"),
"500",
["blur"]
);
// Edit invoice second amount
var $buttonReconcile = widget.$("button.o_reconcile:not(hidden)");
await testUtils.dom.click(widget.$(".edit_amount:last()"));
await testUtils.fields.editAndTrigger(
widget.$(".edit_amount_input:last()"),
"675",
["blur"]
);
assert.equal(
$buttonReconcile.length,
1,
"The reconcile button must be visible"
);
await testUtils.dom.click($buttonReconcile, {allowInvisible: true});
clientAction.destroy();
}
);
QUnit.test(
"Manual Reconciliation: remove a prop to attain balance and reconcile",
async function (assert) {
assert.expect(5);
// Tweak the data to fit our needs
this.params.data_for_manual_reconciliation_widget[
'[283, null, "", 0, 6]'
] = _.extend(
{},
this.params.data_for_manual_reconciliation_widget[
"[null,[282,283,284,285,286,287,288,308,499,500,501,502,503,504]]"
]
);
this.params.data_for_manual_reconciliation_widget[
'[283, null, "", 0, 6]'
].accounts[0].reconciliation_proposition = [
{
account_id: 283,
account_type: "other",
amount_currency_str: "",
currency_id: false,
date_maturity: "2017-03-18",
date: "2017-02-16",
total_amount_str: "$ 500.00",
partner_id: 8,
account_name: "101000 Current Assets",
name: "INV/2017/0987",
partner_name: "Agrolait",
total_amount_currency_str: "",
id: 999,
credit: 0.0,
journal_id: [1, "Customer Invoices"],
amount_str: "$ 500.00",
debit: 500.0,
account_code: "101000",
ref: "",
already_paid: false,
},
];
var clientAction = new ReconciliationClientAction.ManualAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
mockRPC: function (route, args) {
if (args.method === "process_move_lines") {
assert.deepEqual(
args.args,
[
[
{
id: null,
type: null,
mv_line_ids: [399, 402],
new_mv_line_dicts: [],
},
],
],
"should call process_move_lines without the new mv line dict"
);
}
return this._super(route, args);
},
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
// The first reconciliation "line" is where it happens
var widget = clientAction.widgets[0];
// Add first prop
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
assert.equal(
widget.$(".cell_right .edit_amount").length,
0,
"should not display the pencil to edit amount"
);
// Add second prop
await testUtils.dom.click(
widget.$(".match:first .cell_account_code:first")
);
// Check that a create form is here
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
var writeOffCreate = widget.$("div.create");
assert.equal(
writeOffCreate.length,
1,
"A write-off creation should be present"
);
assert.equal(
writeOffCreate.find("input[name=amount]").val(),
500,
"The right amount should be proposed for the write-off"
);
// Remove the first line, the other two will balance one another
await testUtils.dom.click(
widget.$('tr[data-line-id="999"] td:first')
);
var $buttonReconcile = widget.$("button.o_reconcile:visible");
assert.equal(
$buttonReconcile.length,
1,
"The reconcile button must be visible"
);
await testUtils.dom.click($buttonReconcile);
clientAction.destroy();
}
);
QUnit.test("Manual Reconciliation: No lines for account", async function (
assert
) {
assert.expect(2);
var clientAction = new ReconciliationClientAction.ManualAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
// The second reconciliation "line" is where it happens
var widget = clientAction.widgets[1];
var emptyLine = widget.$("tr.mv_line");
assert.notOk(
"data-line-id" in emptyLine.getAttributes(),
"Empty line should be empty"
);
await testUtils.dom.click(emptyLine.find("td:first"));
// Check that a create form is here
var writeOffCreate = widget.$("div.create .create_account_id");
assert.equal(
writeOffCreate.length,
1,
"A write-off creation should be present"
);
clientAction.destroy();
});
QUnit.test("Tax on account receivable", async function (assert) {
assert.expect(21);
this.params.data_for_manual_reconciliation_widget[
"[null,[282,283,284,285,286,287,288,308,499,500,501,502,503,504]]"
].accounts = [];
var clientAction = new ReconciliationClientAction.ManualAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {},
mockRPC: function (route, args) {
if (args.method === "name_search") {
switch (args.model) {
// Mock the default mock to do the minimal processing required
// to get the available values for the droplists.
case "account.account":
assert.step("Account");
return Promise.resolve(
_.map(this.data[args.model].records, function (
record
) {
return [record.id, record.name];
})
);
case "account.tax":
assert.step("Tax");
return Promise.resolve(
_.map(this.data[args.model].records, function (
record
) {
return [record.id, record.display_name];
})
);
case "account.journal":
assert.step("Journal");
return Promise.resolve(
_.map(this.data[args.model].records, function (
record
) {
return [record.id, record.display_name];
})
);
}
}
if (args.method === "process_move_lines") {
var mv_line_ids = args.args[0][0].mv_line_ids.slice(0);
mv_line_ids.sort(function (a, b) {
return a - b;
});
assert.deepEqual(
mv_line_ids,
[6, 19, 21],
"Reconciliation rpc payload, mv_line_ids are correct"
);
// Index aiming at the correct object in the list
var idx = _.has(
args.args[0][0].new_mv_line_dicts[0],
"journal_id"
)
? 0
: 1;
assert.deepEqual(
_.pick(
args.args[0][0].new_mv_line_dicts[idx],
"account_id",
"name",
"credit",
"debit",
"journal_id"
),
{
account_id: 287,
name: "dummy text",
credit: 0,
debit: 180,
journal_id: 8,
},
"Reconciliation rpc payload, new_mv_line_dicts.gift is correct"
);
assert.deepEqual(
_.pick(
args.args[0][0].new_mv_line_dicts[1 - idx],
"account_id",
"name",
"credit",
"debit",
"tax_repartition_line_id"
),
{
account_id: 287,
name: "Tax 20.00%",
credit: 0,
debit: 36,
tax_repartition_line_id: 2,
},
"Reconciliation rpc payload, new_mv_line_dicts.tax is correct"
);
}
return this._super.apply(this, arguments);
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
var widget = clientAction.widgets[0];
// Select invoice of 1k$, payment of 1k$ and payment of 180$
var $tableToReconcile = widget.$(".match");
var defs = _.map([6, 19, 21], function (id) {
return testUtils.dom.click(
$tableToReconcile.find(
"tr.mv_line[data-line-id=" + id + "]:first td:first-child"
)
);
});
await Promise.all(defs);
assert.verifySteps([], "No rpc done");
// Store the money in excess to the "account receivable" account with 20% taxes
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
var $reconcileForm = widget.$(".create");
await testUtils.dom.click(
$reconcileForm.find(".create_account_id input")
);
$(
".ui-autocomplete .ui-menu-item a:contains(101200 Account Receivable)"
)
.trigger("mouseover")
.trigger("click");
await testUtils.nextTick();
assert.verifySteps(["Account"], "Account rpc done");
await testUtils.dom.click($reconcileForm.find(".create_tax_id input"));
$(".ui-autocomplete .ui-menu-item a:contains(Tax 20.00%)")
.trigger("mouseover")
.trigger("click");
await testUtils.nextTick();
assert.verifySteps(["Tax"], "Tax rpc done");
await testUtils.dom.click(
$reconcileForm.find(".create_journal_id input"),
{allowInvisible: true}
);
$(".ui-autocomplete .ui-menu-item a:contains(company 1 journal)")
.trigger("mouseover")
.trigger("click");
await testUtils.nextTick();
await testUtils.fields.editAndTrigger(
$reconcileForm.find(".create_label input"),
"dummy text",
"input"
);
await testUtils.dom.click($reconcileForm.find(".create_label input"));
assert.verifySteps(["Journal"], "Journal rpc done");
// Verify the two (gift + tax) lines were added to the list
var $newLines = widget.$("tr.mv_line[data-line-id^=createLine]");
var idx =
$($($newLines[0]).find("td")[3]).text().trim() === "dummy text"
? 0
: 1;
var $newLineGiftTds = $($newLines[1 - idx]).find("td");
assert.equal(
$($newLineGiftTds[0])
.text()
.trim()
.replace(/[\u200B]/g, ""),
"101200",
"Gift line account number is valid"
);
assert.equal(
$($newLineGiftTds[1]).text().trim(),
"New",
"Gift line is flagged as new"
);
assert.equal(
$($newLineGiftTds[2]).text().trim(),
"dummy text",
"Gift line has the correct label"
);
assert.equal(
$($newLineGiftTds[3]).text().trim(),
"180.00",
"Gift line has the correct left amount"
);
assert.equal(
$($newLineGiftTds[4]).text().trim(),
"",
"Gift line has the correct right amount"
);
var $newLineTaxeTds = $($newLines[idx]).find("td");
assert.equal(
$($newLineTaxeTds[0])
.text()
.trim()
.replace(/[\u200B]/g, ""),
"101200",
"Tax line account number is valid"
);
assert.equal(
$($newLineTaxeTds[1]).text().trim(),
"New",
"Tax line is flagged as new"
);
assert.equal(
$($newLineTaxeTds[2]).text().trim(),
"Tax 20.00%",
"Tax line has the correct label"
);
assert.equal(
$($newLineTaxeTds[3]).text().trim(),
"36.00",
"Tax line has the correct left amount"
);
assert.equal(
$($newLineTaxeTds[4]).text().trim(),
"",
"Tax line has the correct right amount"
);
// Reconcile
await testUtils.dom.click(
widget.$("button.o_reconcile.btn.btn-primary:first")
);
assert.ok(true, "No error in reconciliation");
clientAction.destroy();
});
QUnit.test("Reconcile temporarily and ask to check", async function (
assert
) {
assert.expect(4);
this.params.options.context.to_check = true;
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.mock.addMockEnvironment(clientAction, {
data: this.params.data,
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
var widget = clientAction.widgets[0];
// Add a line as proposition
// open the first line
await testUtils.nextTick();
await testUtils.dom.click(
widget.$(".accounting_view tfoot td.cell_label")
);
await testUtils.dom.click(
widget.$('.o_notebook .nav-link[href*="notebook_page_create"]')
);
var $reconcileForm = widget.$(".create");
$reconcileForm
.find(".create_account_id input")
.val("499001 Suspense Account")
.keydown()
.keyup();
await testUtils.dom.click(
$reconcileForm.find(".create_account_id input")
);
$(".ui-autocomplete .ui-menu-item a:contains(499001 Suspense Account)")
.trigger("mouseover")
.trigger("click");
await testUtils.nextTick();
assert.equal(
$("button.o_validate.btn.btn-secondary.text-warning:first").length,
0,
"should not display reconcile button in orange"
);
await testUtils.dom.click(
$reconcileForm.find(".create_to_check input")
);
assert.equal(
$("button.o_validate.btn.btn-secondary.text-warning:first").length,
1,
"should display reconcile button in orange"
);
testUtils.mock.intercept(clientAction, "call_service", function (
event
) {
assert.deepEqual(
event.data.args[1].args,
[
[5],
[
{
partner_id: 8,
counterpart_aml_dicts: [],
payment_aml_ids: [],
new_aml_dicts: [
{
account_id: 499,
credit: 1175,
debit: 0,
analytic_tag_ids: [[6, null, []]],
name: "SAJ/2014/002 and SAJ/2014/003",
},
],
to_check: true,
},
],
],
"Should call process_bank_statement_line with to_check set to true"
);
var def = testUtils.makeTestPromise();
def.abort = function () {};
event.data.callback(def);
});
await testUtils.dom.click(
widget.$("button.o_validate.btn.btn-secondary:first")
);
assert.ok(true, "No error in reconciliation");
clientAction.destroy();
});
QUnit.test("Reconciliation Models handle analytic tags", async function (
assert
) {
assert.expect(6);
var clientAction = new ReconciliationClientAction.StatementAction(
null,
this.params.options
);
testUtils.addMockEnvironment(clientAction, {
data: this.params.data,
mockRPC: function (route, args) {
if (args.method === "process_bank_statement_line") {
var new_aml_dicts = args.args[1][0].new_aml_dicts;
assert.strictEqual(new_aml_dicts.length, 2);
// I personnally judge the following use case rotten, since
// the first and the second line wouldn't have the same tags
assert.deepEqual(new_aml_dicts[0].analytic_tag_ids, [
[6, null, [1, 2]],
]);
assert.deepEqual(new_aml_dicts[1].analytic_tag_ids, [
[6, null, [2]],
]);
}
return this._super(route, args);
},
session: {
currencies: {
3: {
digits: [69, 2],
position: "before",
symbol: "$",
},
},
user_has_group: function (group) {
if (
group === "analytic.group_analytic_tags" ||
group === "analytic.group_analytic_accounting"
) {
return $.when(true);
}
return this._super.apply(this, arguments);
},
},
archs: {
"account.bank.statement.line,false,search":
'',
},
});
await clientAction.appendTo($("#qunit-fixture"));
await testUtils.nextTick();
// The first reconciliation "line" is where it happens
var widget = clientAction.widgets[0];
await testUtilsDom.click(widget.$(".nav-create:visible"));
await testUtilsDom.click(
widget.$('.quick_add button:contains("Double")')
);
assert.containsN(
widget,
".create_analytic_tag_ids .o_field_many2manytags .badge",
2,
"Two tags are loaded"
);
assert.containsOnce(
widget,
'.create_analytic_tag_ids .o_field_many2manytags .badge:contains("Come together")',
"Tags should have a name"
);
assert.containsOnce(
widget,
'.create_analytic_tag_ids .o_field_many2manytags .badge:contains("Right now")',
"Tags should have a name"
);
await testUtilsDom.click(
widget.$(
".create_analytic_tag_ids .o_field_many2manytags .badge a.o_delete:first()"
)
);
await testUtilsDom.click(widget.$(".o_reconcile:visible"));
clientAction.destroy();
});
}
);
});