[ADD] account_voucher: added yaml for multicurrency i.e. USD-EUR, EUR-EUR, CAD-CHF
bzr revid: mtr@mtr-20110801130143-wygzy83cztuqw3ub
This commit is contained in:
parent
db61756ea7
commit
0465909c92
|
@ -59,7 +59,10 @@ Account Voucher module includes all the basic requirements of Voucher Entries fo
|
|||
"test/account_voucher.yml",
|
||||
"test/sales_receipt.yml",
|
||||
"test/sales_payment.yml",
|
||||
"test/account_voucher_report.yml"
|
||||
"test/account_voucher_report.yml",
|
||||
"test/case2_usd_eur.yml",
|
||||
"test/case3_eur_eur.yml",
|
||||
"test/case4_cad_chf.yml",
|
||||
],
|
||||
'certificate': '0037580727101',
|
||||
"active": False,
|
||||
|
|
|
@ -0,0 +1,360 @@
|
|||
-
|
||||
I create a currency rate for USD for january of 1.333333
|
||||
-
|
||||
!record {model: res.currency.rate, id: janu_usd}:
|
||||
currency_id: base.USD
|
||||
name: !eval "'%s-01-01' %(datetime.now().year)"
|
||||
rate: 1.333333
|
||||
-
|
||||
I create a currency rate for USD for february of 1.250000
|
||||
-
|
||||
!record {model: res.currency.rate, id: febr_usd}:
|
||||
currency_id: base.USD
|
||||
name: !eval "'%s-02-01' %(datetime.now().year)"
|
||||
rate: 1.250000
|
||||
-
|
||||
I create a currency rate for USD for march of 1.111111
|
||||
-
|
||||
!record {model: res.currency.rate, id: marc_usd}:
|
||||
currency_id: base.USD
|
||||
name: !eval "'%s-03-01' %(datetime.now().year)"
|
||||
rate: 1.111111
|
||||
-
|
||||
I create a currency rate for USD for april of 1.052632
|
||||
-
|
||||
!record {model: res.currency.rate, id: apri_usd}:
|
||||
currency_id: base.USD
|
||||
name: !eval "'%s-04-01' %(datetime.now().year)"
|
||||
rate: 1.052632
|
||||
-
|
||||
I create a bank journal with EUR as currency
|
||||
-
|
||||
!record {model: account.journal, id: bank_journal_EUR}:
|
||||
name: Bank Journal(EUR)
|
||||
code: BEUR
|
||||
type: bank
|
||||
analytic_journal_id: account.sit
|
||||
sequence_id: account.sequence_bank_journal
|
||||
default_debit_account_id: account.cash
|
||||
default_credit_account_id: account.cash
|
||||
currency: base.EUR
|
||||
company_id: base.main_company
|
||||
view_id: account.account_journal_bank_view
|
||||
-
|
||||
I create a bank journal with USD as currency
|
||||
-
|
||||
!record {model: account.journal, id: bank_journal_USD}:
|
||||
name: Bank Journal(USD)
|
||||
code: BUSD
|
||||
type: bank
|
||||
analytic_journal_id: account.sit
|
||||
sequence_id: account.sequence_bank_journal
|
||||
default_debit_account_id: account.cash
|
||||
default_credit_account_id: account.cash
|
||||
currency: base.USD
|
||||
company_id: base.main_company
|
||||
view_id: account.account_journal_bank_view
|
||||
-
|
||||
I assign accounts for 'Income Curreny Rate' and 'Expense Currency Rate'
|
||||
-
|
||||
!record {model: res.company, id: base.main_company}:
|
||||
property_expense_currency_exchange: account.o_expense
|
||||
property_income_currency_exchange: account.o_income
|
||||
-
|
||||
I create a new partner Michael Geller
|
||||
-
|
||||
!record {model: res.partner, id: res_partner_michael0}:
|
||||
address:
|
||||
- city: paris
|
||||
country_id: base.fr
|
||||
name: Michael
|
||||
street: 1 rue Rockfeller
|
||||
type: invoice
|
||||
zip: '75016'
|
||||
name: Mr.Michael Geller
|
||||
-
|
||||
I create the first invoice on 1st January for 200 USD
|
||||
-
|
||||
!record {model: account.invoice, id: account_first_invoice_jan}:
|
||||
account_id: account.a_recv
|
||||
address_contact_id: base.res_partner_address_3000
|
||||
address_invoice_id: base.res_partner_address_3000
|
||||
company_id: base.main_company
|
||||
currency_id: base.USD
|
||||
date_invoice: !eval "'%s-01-01' %(datetime.now().year)"
|
||||
period_id: account.period_1
|
||||
invoice_line:
|
||||
- account_id: account.a_sale
|
||||
name: '[PC1] Basic PC'
|
||||
price_unit: 200.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_pc1
|
||||
uos_id: product.product_uom_unit
|
||||
journal_id: account.sales_journal
|
||||
partner_id: res_partner_michael0
|
||||
reference_type: none
|
||||
-
|
||||
I Validate invoice by clicking on Validate button
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: account_first_invoice_jan}
|
||||
-
|
||||
I check that first invoice move is correct
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan"))
|
||||
assert invoice_id.move_id, "Move not created for open invoice"
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
assert (move_line.debit - move_line.credit == 150.00), "Invoice move is incorrect for debtors account"
|
||||
-
|
||||
I create the second invoice on 1st February for 100 USD
|
||||
-
|
||||
!record {model: account.invoice, id: account_second_invoice_feb}:
|
||||
account_id: account.a_recv
|
||||
address_contact_id: base.res_partner_address_3000
|
||||
address_invoice_id: base.res_partner_address_3000
|
||||
company_id: base.main_company
|
||||
currency_id: base.USD
|
||||
date_invoice: !eval "'%s-02-01' %(datetime.now().year)"
|
||||
period_id: account.period_2
|
||||
invoice_line:
|
||||
- account_id: account.a_sale
|
||||
name: '[PC1] Basic PC'
|
||||
price_unit: 100.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_pc1
|
||||
uos_id: product.product_uom_unit
|
||||
journal_id: account.sales_journal
|
||||
partner_id: res_partner_michael0
|
||||
reference_type: none
|
||||
-
|
||||
I Validate invoice by clicking on Validate button
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: account_second_invoice_feb}
|
||||
-
|
||||
I check that second invoice move is correct for debtor account (debit - credit == 80)
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_second_invoice_feb"))
|
||||
assert invoice_id.move_id, "Move not created for open invoice"
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
assert (move_line.debit - move_line.credit == 80), "Invoice move is incorrect for debtors account"
|
||||
-
|
||||
I create the first voucher of payment with values 240 EUR, journal EUR, and fill amount 180 for the invoice of 200$ and 70 for the 100$ invoice.
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc, time
|
||||
vals = {}
|
||||
res = self.onchange_partner_id(cr, uid, [], ref("res_partner_michael0"), ref('bank_journal_EUR'), 240.0, 2, ttype='receipt', date=False)
|
||||
vals = {
|
||||
'account_id': ref('account.cash'),
|
||||
'amount': 240.0,
|
||||
'company_id': ref('base.main_company'),
|
||||
'currency_id': ref('base.EUR'),
|
||||
'journal_id': ref('bank_journal_EUR'),
|
||||
'partner_id': ref('res_partner_michael0'),
|
||||
'period_id': ref('account.period_3'),
|
||||
'type': 'receipt',
|
||||
'date': time.strftime("%Y-03-01"),
|
||||
'payment_option': 'with_writeoff',
|
||||
'writeoff_acc_id': ref('account.a_expense'),
|
||||
'comment': 'Write Off',
|
||||
'name': 'First payment',
|
||||
}
|
||||
if not res['value']['line_cr_ids']:
|
||||
res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}]
|
||||
for item in res['value']['line_cr_ids']:
|
||||
if item['amount_unreconciled'] == 200:
|
||||
item['amount'] = 180
|
||||
else:
|
||||
item['amount'] = 70
|
||||
vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']]
|
||||
id = self.create(cr, uid, vals)
|
||||
voucher_id = self.browse(cr, uid, id)
|
||||
assert (voucher_id.state=='draft'), "Voucher is not in draft state"
|
||||
-
|
||||
I check that writeoff amount computed is 15
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert (voucher_id.writeoff_amount == 15), "writeoff amount is not 15"
|
||||
-
|
||||
I check that currency rate difference is -34
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert (voucher_id.currency_rate_difference == -34), "currency rate difference is not -34"
|
||||
-
|
||||
I confirm the voucher
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_validate(uid, 'account.voucher', voucher[0], 'proforma_voucher', cr)
|
||||
-
|
||||
I check that my voucher state is posted
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert voucher_id.state == 'posted', "Voucher state is not posted"
|
||||
-
|
||||
I check that my debtor account is correct
|
||||
-
|
||||
I check that the debtor account has 2 new lines with -180 and -70 as amount_currency columns and their credit columns are respectively 135 and 56 and currency is USD($).
|
||||
-
|
||||
I check that my Currency Difference entry is created with a credit of 34, amount currency as 0.0
|
||||
-
|
||||
I check that my write-off entry is created with a credit of 15.00 and amount currency as 0.0
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment')])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)])
|
||||
for move_line in move_line_obj.browse(cr, uid, move_lines):
|
||||
if move_line.amount_currency == -180:
|
||||
assert move_line.credit == 135, "Debtor account has wrong entry."
|
||||
if move_line.amount_currency == -70:
|
||||
assert move_line.credit == 56.00, "Debtor account has wrong entry."
|
||||
if move_line.credit == 34:
|
||||
assert move_line.amount_currency == 0.00, "Incorrect Currency Difference."
|
||||
if move_line.credit == 15.00:
|
||||
assert move_line.credit == 0.00, "Writeoff amount is wrong."
|
||||
-
|
||||
I check the residual amount of Invoice1, should be 20 in residual currency and 15 in amount_residual
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for first Invoice"
|
||||
-
|
||||
I check the residual amuont of Invoice2, should be 30 in residual currency and 24 in amount_residual
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_second_invoice_feb"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for second Invoice"
|
||||
-
|
||||
I create the second voucher of payment with values, 45 USD, journal USD, and fill amounts 20 for the invoice of 200$ and 30 for the invoice of 100$
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc, time
|
||||
vals = {}
|
||||
res = self.onchange_partner_id(cr, uid, [], ref("res_partner_michael0"), ref('bank_journal_EUR'), 45.0, 2, ttype='receipt', date=False)
|
||||
vals = {
|
||||
'account_id': ref('account.cash'),
|
||||
'amount': 45.0,
|
||||
'company_id': ref('base.main_company'),
|
||||
'currency_id': ref('base.USD'),
|
||||
'journal_id': ref('bank_journal_USD'),
|
||||
'partner_id': ref('res_partner_michael0'),
|
||||
'period_id': ref('account.period_3'),
|
||||
'type': 'receipt',
|
||||
'date': time.strftime("%Y-04-01"),
|
||||
'payment_option': 'with_writeoff',
|
||||
'writeoff_acc_id': ref('account.a_expense'),
|
||||
'comment': 'Write Off',
|
||||
'name': 'Second payment',
|
||||
}
|
||||
if not res['value']['line_cr_ids']:
|
||||
res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}]
|
||||
for item in res['value']['line_cr_ids']:
|
||||
if item['amount_unreconciled'] == 20:
|
||||
item['amount'] = 20
|
||||
else:
|
||||
item['amount'] = 30
|
||||
vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']]
|
||||
id = self.create(cr, uid, vals)
|
||||
voucher_id = self.browse(cr, uid, id)
|
||||
assert (voucher_id.state=='draft'), "Voucher is not in draft state"
|
||||
-
|
||||
I check that writeoff amount computed is -5
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert (voucher_id.writeoff_amount == -5), "writeoff amount is not -5"
|
||||
-
|
||||
I check that currency rate difference is -8.50
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
curr_diff = voucher_id.currency_rate_difference
|
||||
assert (voucher_id.currency_rate_difference == curr_diff), "currency rate difference is not -8.50"
|
||||
-
|
||||
I confirm the voucher
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_validate(uid, 'account.voucher', voucher[0], 'proforma_voucher', cr)
|
||||
-
|
||||
I check that my voucher state is posted
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert voucher_id.state == 'posted', "Voucher state is not posted"
|
||||
-
|
||||
I check that my debtor account is correct
|
||||
-
|
||||
I check that the debtor account has 2 new lines with -20 and -30 as amount_currency columns and their credit columns are respectively 15 and 24 and currency is USD($).
|
||||
-
|
||||
I check that my Currency Difference entry is created with a credit of 8.5
|
||||
-
|
||||
I check that my write-off entry is created with a debit of 4.75 and amount currency as 0.0
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_michael0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)])
|
||||
for move_line in move_line_obj.browse(cr, uid, move_lines):
|
||||
d
|
||||
if move_line.amount_currency == -20:
|
||||
assert move_line.credit == 15, "Debtor account has wrong entry."
|
||||
if move_line.amount_currency == -30:
|
||||
assert move_line.credit == 24, "Debtor account has wrong entry."
|
||||
if move_line.credit == 8.5:
|
||||
assert move_line.amount_currency == 0.00, "Incorrect Currency Difference."
|
||||
if move_line.credit == 5:
|
||||
assert move_line.credit == 4.75, "Writeoff amount is wrong."
|
||||
-
|
||||
I check the residual amount of invoice 1, should be 0 in residual currency and 0 in amount_residual
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for first Invoice"
|
||||
-
|
||||
I check the residual amuont of invoice 2, should be 0 in residual currency and 0 in amount_residual
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_second_invoice_feb"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for second Invoice"
|
|
@ -0,0 +1,331 @@
|
|||
-
|
||||
I create a currency rate for EUR for january of 1.000000
|
||||
-
|
||||
!record {model: res.currency.rate, id: jan_eur}:
|
||||
currency_id: base.EUR
|
||||
name: !eval "'%s-01-01' %(datetime.now().year)"
|
||||
rate: 1.000000
|
||||
-
|
||||
I create a currency rate for EUR for february of 1.000000
|
||||
-
|
||||
!record {model: res.currency.rate, id: feb_eur}:
|
||||
currency_id: base.EUR
|
||||
name: !eval "'%s-02-01' %(datetime.now().year)"
|
||||
rate: 1.000000
|
||||
-
|
||||
I create a currency rate for EUR for march of 1.000000
|
||||
-
|
||||
!record {model: res.currency.rate, id: mar_eur}:
|
||||
currency_id: base.EUR
|
||||
name: !eval "'%s-03-01' %(datetime.now().year)"
|
||||
rate: 1.000000
|
||||
-
|
||||
I create a currency rate for EUR for april of 1.000000
|
||||
-
|
||||
!record {model: res.currency.rate, id: apr_eur}:
|
||||
currency_id: base.EUR
|
||||
name: !eval "'%s-04-01' %(datetime.now().year)"
|
||||
rate: 1.000000
|
||||
-
|
||||
I create a bank journal with EUR as currency
|
||||
-
|
||||
!record {model: account.journal, id: bank_journal_EUR}:
|
||||
name: Bank Journal(EUR)
|
||||
code: BEUR
|
||||
type: bank
|
||||
analytic_journal_id: account.sit
|
||||
sequence_id: account.sequence_bank_journal
|
||||
default_debit_account_id: account.cash
|
||||
default_credit_account_id: account.cash
|
||||
currency: base.EUR
|
||||
company_id: base.main_company
|
||||
view_id: account.account_journal_bank_view
|
||||
-
|
||||
I assign accounts for 'Income Curreny Rate' and 'Expense Currency Rate'
|
||||
-
|
||||
!record {model: res.company, id: base.main_company}:
|
||||
property_expense_currency_exchange: account.o_expense
|
||||
property_income_currency_exchange: account.o_income
|
||||
-
|
||||
I create a new partner Peter Lawson.
|
||||
-
|
||||
!record {model: res.partner, id: res_partner_peter0}:
|
||||
address:
|
||||
- city: paris
|
||||
country_id: base.fr
|
||||
name: Peter
|
||||
street: 1 rue Rockfeller
|
||||
type: invoice
|
||||
zip: '75016'
|
||||
name: Mr.Peter Lawson
|
||||
-
|
||||
I create the first invoice on 1st January for 150 EUR
|
||||
-
|
||||
!record {model: account.invoice, id: account_first_invoice_jan_eur}:
|
||||
account_id: account.a_recv
|
||||
address_contact_id: base.res_partner_address_3000
|
||||
address_invoice_id: base.res_partner_address_3000
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
date_invoice: !eval "'%s-01-01' %(datetime.now().year)"
|
||||
period_id: account.period_1
|
||||
invoice_line:
|
||||
- account_id: account.a_sale
|
||||
name: '[PC1] Basic PC'
|
||||
price_unit: 150.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_pc1
|
||||
uos_id: product.product_uom_unit
|
||||
journal_id: account.sales_journal
|
||||
partner_id: res_partner_peter0
|
||||
reference_type: none
|
||||
-
|
||||
I Validate invoice by clicking on Validate button
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: account_first_invoice_jan_eur}
|
||||
-
|
||||
I check that first invoice move is correct
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan_eur"))
|
||||
assert invoice_id.move_id, "Move not created for open invoice"
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
assert (move_line.debit - move_line.credit == 150.00), "Invoice move is incorrect for debtors account"
|
||||
-
|
||||
I create the first invoice on 1st February for 80 EUR
|
||||
-
|
||||
!record {model: account.invoice, id: account_second_invoice_feb_eur}:
|
||||
account_id: account.a_recv
|
||||
address_contact_id: base.res_partner_address_3000
|
||||
address_invoice_id: base.res_partner_address_3000
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
date_invoice: !eval "'%s-02-01' %(datetime.now().year)"
|
||||
period_id: account.period_1
|
||||
invoice_line:
|
||||
- account_id: account.a_sale
|
||||
name: '[PC1] Basic PC'
|
||||
price_unit: 80.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_pc1
|
||||
uos_id: product.product_uom_unit
|
||||
journal_id: account.sales_journal
|
||||
partner_id: res_partner_peter0
|
||||
reference_type: none
|
||||
-
|
||||
I Validate invoice by clicking on Validate button
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: account_second_invoice_feb_eur}
|
||||
-
|
||||
I check that second invoice move is correct
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_second_invoice_feb_eur"))
|
||||
assert invoice_id.move_id, "Move not created for open invoice"
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
assert (move_line.debit - move_line.credit == 80.00), "Invoice move is incorrect for debtors account"
|
||||
-
|
||||
I create the first voucher of payment with values 120 EUR, journal EUR, and fill amounts 100 for the invoice of 150 and 20 for the 80 EUR invoice.
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc, time
|
||||
vals = {}
|
||||
res = self.onchange_partner_id(cr, uid, [], ref("res_partner_peter0"), ref('bank_journal_EUR'), 120.00, 2, ttype='receipt', date=False)
|
||||
vals = {
|
||||
'account_id': ref('account.cash'),
|
||||
'amount': 120.0,
|
||||
'company_id': ref('base.main_company'),
|
||||
'currency_id': ref('base.EUR'),
|
||||
'journal_id': ref('bank_journal_EUR'),
|
||||
'partner_id': ref('res_partner_peter0'),
|
||||
'period_id': ref('account.period_3'),
|
||||
'type': 'receipt',
|
||||
'date': time.strftime("%Y-03-01"),
|
||||
'payment_option': 'with_writeoff',
|
||||
'writeoff_acc_id': ref('account.a_expense'),
|
||||
'comment': 'Write Off',
|
||||
'name': 'First payment',
|
||||
}
|
||||
if not res['value']['line_cr_ids']:
|
||||
res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}]
|
||||
for item in res['value']['line_cr_ids']:
|
||||
if item['amount_unreconciled'] == 150:
|
||||
item['amount'] = 100
|
||||
else:
|
||||
item['amount'] = 20
|
||||
vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']]
|
||||
id = self.create(cr, uid, vals)
|
||||
voucher_id = self.browse(cr, uid, id)
|
||||
assert (voucher_id.state=='draft'), "Voucher is not in draft state"
|
||||
-
|
||||
I check that writeoff amount computed is 0
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'),('partner_id', '=', ref('res_partner_peter0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert (voucher_id.writeoff_amount == 0), "writeoff amount is not 0"
|
||||
-
|
||||
I check that currency rate difference is 0.00
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'),('partner_id', '=', ref('res_partner_peter0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert (voucher_id.currency_rate_difference == 0.00), "currency rate difference is not 0.00"
|
||||
-
|
||||
I confirm the voucher
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'),('partner_id', '=', ref('res_partner_peter0'))])
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_validate(uid, 'account.voucher', voucher[0], 'proforma_voucher', cr)
|
||||
-
|
||||
I check that my voucher state is posted
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'),('partner_id', '=', ref('res_partner_peter0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert voucher_id.state == 'posted', "Voucher state is not posted"
|
||||
-
|
||||
I check that my debtor account is correct
|
||||
-
|
||||
I check that the debtor account has 2 new lines with 0.00 and 0.00 as amount_currency columns and their credit are 20 and 100 respectively
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment'),('partner_id', '=', ref('res_partner_peter0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)])
|
||||
for move_line in move_line_obj.browse(cr, uid, move_lines):
|
||||
if move_line.credit == 20:
|
||||
assert move_line.amount_currency == 0.00, "Debtor account has wrong entry."
|
||||
if move_line.credit == 100:
|
||||
assert move_line.amount_currency == 0.00, "Debtor account has wrong entry."
|
||||
-
|
||||
I check the residual amount of Invoice1 is 50
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan_eur"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for first Invoice"
|
||||
-
|
||||
I check the residual amuont of Invoice2 is 60
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_second_invoice_feb_eur"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for second Invoice"
|
||||
-
|
||||
I create the second voucher of payment and check to let open the debtor overpaid amount.
|
||||
-
|
||||
I create the second voucher of payment with Paid Amount as 120, journal EUR, and fill amount 50 for the residual amount 50 for the invoice of 150 and 70 for the residual amount 60 for the invoice of 80
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc, time
|
||||
vals = {}
|
||||
res = self.onchange_partner_id(cr, uid, [], ref("res_partner_peter0"), ref('bank_journal_EUR'), 120.0, 2, ttype='receipt', date=False)
|
||||
vals = {
|
||||
'account_id': ref('account.cash'),
|
||||
'amount': 120.0,
|
||||
'company_id': ref('base.main_company'),
|
||||
'currency_id': ref('base.EUR'),
|
||||
'journal_id': ref('bank_journal_EUR'),
|
||||
'partner_id': ref('res_partner_peter0'),
|
||||
'period_id': ref('account.period_3'),
|
||||
'type': 'receipt',
|
||||
'date': time.strftime("%Y-04-01"),
|
||||
'payment_option': 'with_writeoff',
|
||||
'writeoff_acc_id': ref('account.a_expense'),
|
||||
'comment': 'Write Off',
|
||||
'name': 'Second payment',
|
||||
}
|
||||
if not res['value']['line_cr_ids']:
|
||||
res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}]
|
||||
for item in res['value']['line_cr_ids']:
|
||||
if item['amount_unreconciled'] == 50.00:
|
||||
item['amount'] = 50.00
|
||||
elif item['amount_unreconciled'] == 60.00:
|
||||
item['amount'] = 70.00
|
||||
vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']]
|
||||
id = self.create(cr, uid, vals)
|
||||
voucher_id = self.browse(cr, uid, id)
|
||||
assert (voucher_id.state=='draft'), "Voucher is not in draft state"
|
||||
-
|
||||
I check that writeoff amount computed is 0.00
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'),('partner_id', '=', ref('res_partner_peter0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert (voucher_id.writeoff_amount == 0.00), "writeoff amount is not 0"
|
||||
-
|
||||
I check that currency rate difference is 0.00
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_peter0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
curr_diff = voucher_id.currency_rate_difference
|
||||
assert (voucher_id.currency_rate_difference == curr_diff), "currency rate difference is not 0"
|
||||
-
|
||||
I confirm the voucher
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_peter0'))])
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_validate(uid, 'account.voucher', voucher[0], 'proforma_voucher', cr)
|
||||
-
|
||||
I check that my voucher state is posted
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_peter0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert voucher_id.state == 'posted', "Voucher state is not posted"
|
||||
-
|
||||
I check that my debtor account is correct
|
||||
-
|
||||
I check that the debtor account has 2 new lines with 0.00 and 0.00 as amount_currency columns and their credit are 70 and 50
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment'), ('partner_id', '=', ref('res_partner_peter0'))])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)])
|
||||
for move_line in move_line_obj.browse(cr, uid, move_lines):
|
||||
if move_line.credit == 70.00:
|
||||
assert move_line.amount_currency == 0.00, "Debtor account has wrong entry."
|
||||
if move_line.credit == 50.00:
|
||||
assert move_line.amount_currency == 0.00, "Debtor account has wrong entry."
|
||||
-
|
||||
I check the residual amount of Invoice1 is 0
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan_eur"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for first Invoice"
|
||||
-
|
||||
I check the residual amuont of Invoice2 is -10
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_second_invoice_feb_eur"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for second Invoice"
|
|
@ -0,0 +1,181 @@
|
|||
-
|
||||
I create a currency rate for CAD for january of 1.338800
|
||||
-
|
||||
!record {model: res.currency.rate, id: jan_cad}:
|
||||
currency_id: base.CAD
|
||||
name: !eval "'%s-01-01' %(datetime.now().year)"
|
||||
rate: 1.338800
|
||||
-
|
||||
I create a currency rate for CAD for march of 0.500000
|
||||
-
|
||||
!record {model: res.currency.rate, id: mar_cad}:
|
||||
currency_id: base.CAD
|
||||
name: !eval "'%s-03-01' %(datetime.now().year)"
|
||||
rate: 0.500000
|
||||
-
|
||||
I create a currency rate for CHF for january of 1.308600
|
||||
-
|
||||
!record {model: res.currency.rate, id: jan_chf}:
|
||||
currency_id: base.CHF
|
||||
name: !eval "'%s-01-01' %(datetime.now().year)"
|
||||
rate: 1.308600
|
||||
-
|
||||
I create a bank journal with CHF as currency
|
||||
-
|
||||
!record {model: account.journal, id: bank_journal_CHF}:
|
||||
name: Bank Journal(CHF)
|
||||
code: BCHF
|
||||
type: bank
|
||||
analytic_journal_id: account.sit
|
||||
sequence_id: account.sequence_bank_journal
|
||||
default_debit_account_id: account.cash
|
||||
default_credit_account_id: account.cash
|
||||
currency: base.CHF
|
||||
company_id: base.main_company
|
||||
view_id: account.account_journal_bank_view
|
||||
-
|
||||
I assign accounts for 'Income Curreny Rate' and 'Expense Currency Rate'
|
||||
-
|
||||
!record {model: res.company, id: base.main_company}:
|
||||
property_expense_currency_exchange: account.o_expense
|
||||
property_income_currency_exchange: account.o_income
|
||||
-
|
||||
I create a new partner John Armani.
|
||||
-
|
||||
!record {model: res.partner, id: res_partner_john0}:
|
||||
address:
|
||||
- city: paris
|
||||
country_id: base.fr
|
||||
name: John
|
||||
street: 1 rue Rockfeller
|
||||
type: invoice
|
||||
zip: '75016'
|
||||
name: Mr.John Armani
|
||||
-
|
||||
I create the first invoice on 1st January for 200 CAD
|
||||
-
|
||||
!record {model: account.invoice, id: account_first_invoice_jan_cad}:
|
||||
account_id: account.a_recv
|
||||
address_contact_id: base.res_partner_address_3000
|
||||
address_invoice_id: base.res_partner_address_3000
|
||||
company_id: base.main_company
|
||||
currency_id: base.CAD
|
||||
date_invoice: !eval "'%s-01-01' %(datetime.now().year)"
|
||||
period_id: account.period_1
|
||||
invoice_line:
|
||||
- account_id: account.a_sale
|
||||
name: '[PC1] Basic PC'
|
||||
price_unit: 200.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_pc1
|
||||
uos_id: product.product_uom_unit
|
||||
journal_id: account.sales_journal
|
||||
partner_id: res_partner_john0
|
||||
reference_type: none
|
||||
-
|
||||
I Validate invoice by clicking on Validate button
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: account_first_invoice_jan_cad}
|
||||
-
|
||||
I check that accounting move for first invoice is correct
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan_cad"))
|
||||
assert invoice_id.move_id, "Move not created for open invoice"
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
assert (move_line.debit - move_line.credit == 149.39), "Invoice move is incorrect for debtors account"
|
||||
-
|
||||
I create the first voucher of payment with Paid amount as 300, journal CHF, and fill amounts 200 for the invoice of 200.
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc, time
|
||||
vals = {}
|
||||
res = self.onchange_partner_id(cr, uid, [], ref("res_partner_john0"), ref('bank_journal_CHF'), 300.0, 2, ttype='receipt', date=False)
|
||||
vals = {
|
||||
'account_id': ref('account.cash'),
|
||||
'amount': 120.0,
|
||||
'company_id': ref('base.main_company'),
|
||||
'currency_id': ref('base.CHF'),
|
||||
'journal_id': ref('bank_journal_CHF'),
|
||||
'partner_id': ref('res_partner_john0'),
|
||||
'period_id': ref('account.period_3'),
|
||||
'type': 'receipt',
|
||||
'date': time.strftime("%Y-03-01"),
|
||||
'payment_option': 'with_writeoff',
|
||||
'writeoff_acc_id': ref('account.a_expense'),
|
||||
'comment': 'Write Off',
|
||||
'name': 'First payment',
|
||||
}
|
||||
if not res['value']['line_cr_ids']:
|
||||
res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}]
|
||||
for item in res['value']['line_cr_ids']:
|
||||
if item['amount_unreconciled'] == 200:
|
||||
item['amount'] = 200
|
||||
vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']]
|
||||
id = self.create(cr, uid, vals)
|
||||
voucher_id = self.browse(cr, uid, id)
|
||||
assert (voucher_id.state=='draft'), "Voucher is not in draft state"
|
||||
-
|
||||
I check that writeoff amount computed is 175
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment')])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert (voucher_id.writeoff_amount == 175), "writeoff amount is not 175"
|
||||
-
|
||||
I check that currency rate difference is 49.39
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment')])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert (voucher_id.currency_rate_difference == 49.39), "currency rate difference is not 0.00"
|
||||
-
|
||||
I confirm the voucher
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
import netsvc
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment')])
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_validate(uid, 'account.voucher', voucher[0], 'proforma_voucher', cr)
|
||||
-
|
||||
I check that my voucher state is posted
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment')])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
assert voucher_id.state == 'posted', "Voucher state is not posted"
|
||||
-
|
||||
I check that my debtor account is correct
|
||||
-
|
||||
I check that the debtor account has 2 new lines with -20 and -30 as amount_currency columns and their credit columns are respectively 15 and 24 and currency is USD($).
|
||||
-
|
||||
I check that my Currency Difference entry is created with a credit of 8.5
|
||||
-
|
||||
I check that my write-off entry is created with a debit of 4.75 and amount currency as 0.0
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'Second payment')])
|
||||
voucher_id = self.browse(cr, uid, voucher[0])
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)])
|
||||
for move_line in move_line_obj.browse(cr, uid, move_lines):
|
||||
if move_line.amount_currency == -200:
|
||||
assert move_line.credit == 149.39, "Debtor account has wrong entry."
|
||||
if move_line.credit == 49.39:
|
||||
assert move_line.amount_currency == 0.00, "Incorrect Currency Difference."
|
||||
if move_line.credit == -140.00:
|
||||
assert move_line.credit == -175, "Writeoff amount is wrong."
|
||||
-
|
||||
I check the residual amount of invoice 1, should be 0 in residual currency and 0 in amount_residual
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan"))
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
|
||||
move_line = move_line_obj.browse(cr, uid, move_lines[0])
|
||||
residual_curr = move_line.amount_residual_currency
|
||||
residual = move_line.amount_residual
|
||||
assert (move_line.amount_residual_currency == residual_curr and move_line.amount_residual == residual) , "Residual amount is not correct for first Invoice"
|
||||
-
|
Loading…
Reference in New Issue