codepush
This commit is contained in:
commit
70dda814aa
15
bahmni-addons/LICENSE
Normal file
15
bahmni-addons/LICENSE
Normal file
@ -0,0 +1,15 @@
|
||||
Additional modules for Odoo for Bahmni specific integrations
|
||||
Copyright (C) 2014 OpenMRS, Inc
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2
bahmni-addons/NOTICE
Normal file
2
bahmni-addons/NOTICE
Normal file
@ -0,0 +1,2 @@
|
||||
Copyright (C) 2013 OpenMRS, Inc
|
||||
This product includes software developed under the stewardship of the Bahmni Coalition, under fiscal sponsorship of OpenMRS, Inc. (http://www.openmrs.org/)
|
2
bahmni-addons/README.md
Normal file
2
bahmni-addons/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# odoo-modules
|
||||
Custom Odoo modules (extensions) for Bahmni
|
3
bahmni-addons/bahmni_account/__init__.py
Normal file
3
bahmni-addons/bahmni_account/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import models
|
||||
import report
|
30
bahmni-addons/bahmni_account/__manifest__.py
Normal file
30
bahmni-addons/bahmni_account/__manifest__.py
Normal file
@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': 'Bahmni Account',
|
||||
'version': '1.0',
|
||||
'summary': 'Custom account module to meet bahmni requirement',
|
||||
'sequence': 1,
|
||||
'description': """
|
||||
Bahmni Account
|
||||
====================
|
||||
""",
|
||||
'category': 'Account',
|
||||
'website': '',
|
||||
'images': [],
|
||||
'depends': ['account', 'account_voucher', 'web_readonly_bypass'],
|
||||
'data': [
|
||||
'views/bahmni_account.xml',
|
||||
'views/account_invoice_view.xml',
|
||||
'views/account_config_settings.xml',
|
||||
'report/account_count_report.xml',
|
||||
'report/account_report.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/account_payment.xml',
|
||||
'report/report_invoice_inherit.xml'
|
||||
],
|
||||
'demo': [],
|
||||
'qweb': [],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
}
|
13
bahmni-addons/bahmni_account/data/discount_accounts.xml
Normal file
13
bahmni-addons/bahmni_account/data/discount_accounts.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Account for debiting discount amount-->
|
||||
<record id="account_discount" model="account.account">
|
||||
<field name="name">Discount</field>
|
||||
</record>
|
||||
|
||||
<!--Account for debiting amount which is paid extra-->
|
||||
<record id="account_overcharge" model="account.account">
|
||||
<field name="name">Overcharge</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
19
bahmni-addons/bahmni_account/doc/ChangeLog.txt
Normal file
19
bahmni-addons/bahmni_account/doc/ChangeLog.txt
Normal file
@ -0,0 +1,19 @@
|
||||
1. New fields added to account.invoice for applying discounts on invoices.
|
||||
1. Discount Type : None, Fixed, Percentage
|
||||
2. Discount : Total discount amount getting applied.
|
||||
3. Discount Percentage : If percentage type is selected, then for defining percentage.
|
||||
- if discount type is selected as percentage, then discount field will be readonly,
|
||||
as discount amount will get computed based on given percentage.
|
||||
4. Discount Account Head : Account from/to which discount amount will get credited or debited.
|
||||
2. on change method is defined for discount percentage and invoice lines, to compute discount amount, when type percetage is selected.
|
||||
3. Customer Invoices form is inherited, and footer is defined completely in new way,
|
||||
as default footer class was not making form look good.
|
||||
4. compute_amount method is overridden to change the logic of computing total of invoice, i.e. deduct discount amount from total.
|
||||
5. create method of account_invoice_line is inherited to set value of discount field,
|
||||
when invoice is created through Create Invoice button on Sale Order form.
|
||||
As method which is getting called through that button, is creating invoice object first
|
||||
and then one-by-one invoice lines are getting created.
|
||||
6. rouding.off class defined to set round_off_amount value in account_invoice and sale_order.
|
||||
for calculating this value, configuration is provided to user under Sales > Configuration > Settings menu,
|
||||
where user can set Round Off Value, this is the amount to which value has to get rounded off.
|
||||
|
3
bahmni-addons/bahmni_account/doc/imp_points.txt
Normal file
3
bahmni-addons/bahmni_account/doc/imp_points.txt
Normal file
@ -0,0 +1,3 @@
|
||||
* rounding.off class is kept in bahmni_account module, as it is used in account_invoice and sale_order class.
|
||||
bahmni_sale already has dependency of bahmni_account module, hence this class can be accessed in that module.
|
||||
vice-versa won't happen; as it will be a round dependency.
|
7
bahmni-addons/bahmni_account/models/__init__.py
Normal file
7
bahmni-addons/bahmni_account/models/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import rounding_off
|
||||
import account_invoice
|
||||
import account_invoice_line
|
||||
import account_config_settings
|
||||
import res_company
|
||||
import account_payment
|
BIN
bahmni-addons/bahmni_account/models/__init__.pyc
Normal file
BIN
bahmni-addons/bahmni_account/models/__init__.pyc
Normal file
Binary file not shown.
@ -0,0 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class AccountConfigSettings(models.TransientModel):
|
||||
_inherit = 'account.config.settings'
|
||||
|
||||
round_off_by = fields.Float(string="Round off by", related="company_id.round_off_by")
|
||||
|
||||
@api.multi
|
||||
def set_round_off_by_defaults(self):
|
||||
return self.env['ir.values'].sudo().set_default(
|
||||
'account.config.settings', 'round_off_by', self.round_off_by)
|
||||
|
||||
|
BIN
bahmni-addons/bahmni_account/models/account_config_settings.pyc
Normal file
BIN
bahmni-addons/bahmni_account/models/account_config_settings.pyc
Normal file
Binary file not shown.
286
bahmni-addons/bahmni_account/models/account_invoice.py
Normal file
286
bahmni-addons/bahmni_account/models/account_invoice.py
Normal file
@ -0,0 +1,286 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import fields, models, api, _
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
# mapping invoice type to refund type
|
||||
TYPE2REFUND = {
|
||||
'out_invoice': 'out_refund', # Customer Invoice
|
||||
'in_invoice': 'in_refund', # Vendor Bill
|
||||
'out_refund': 'out_invoice', # Customer Refund
|
||||
'in_refund': 'in_invoice', # Vendor Refund
|
||||
}
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
# # overridden this method to deduct discounted amount from total of invoice
|
||||
@api.one
|
||||
@api.depends('invoice_line_ids.price_subtotal', 'tax_line_ids.amount',
|
||||
'currency_id', 'company_id', 'date_invoice', 'type', 'discount')
|
||||
def _compute_amount(self):
|
||||
round_curr = self.currency_id.round
|
||||
self.amount_untaxed = sum(line.price_subtotal for line in self.invoice_line_ids)
|
||||
self.amount_tax = sum(round_curr(line.amount) for line in self.tax_line_ids)
|
||||
amount_total = self.amount_untaxed + self.amount_tax - self.discount
|
||||
self.round_off_amount = self.env['rounding.off'].round_off_value_to_nearest(amount_total)
|
||||
self.amount_total = self.amount_untaxed + self.amount_tax - self.discount + self.round_off_amount
|
||||
amount_total_company_signed = self.amount_total
|
||||
amount_untaxed_signed = self.amount_untaxed
|
||||
if self.currency_id and self.company_id and self.currency_id != self.company_id.currency_id:
|
||||
currency_id = self.currency_id.with_context(date=self.date_invoice)
|
||||
amount_total_company_signed = currency_id.compute(self.amount_total, self.company_id.currency_id)
|
||||
amount_untaxed_signed = currency_id.compute(self.amount_untaxed, self.company_id.currency_id)
|
||||
sign = self.type in ['in_refund', 'out_refund'] and -1 or 1
|
||||
self.amount_total_company_signed = amount_total_company_signed * sign
|
||||
self.amount_total_signed = self.amount_total * sign
|
||||
self.amount_untaxed_signed = amount_untaxed_signed * sign
|
||||
|
||||
discount_type = fields.Selection([('none', 'No Discount'),
|
||||
('fixed', 'Fixed'),
|
||||
('percentage', 'Percentage')],
|
||||
string="Discount Method",
|
||||
default='none')
|
||||
discount = fields.Monetary(string="Discount")
|
||||
discount_percentage = fields.Float(string="Discount Percentage")
|
||||
disc_acc_id = fields.Many2one('account.account',
|
||||
string="Discount Account Head")
|
||||
round_off_amount = fields.Monetary(string="Round Off Amount",
|
||||
compute=_compute_amount)
|
||||
|
||||
@api.onchange('invoice_line_ids')
|
||||
def onchange_invoice_lines(self):
|
||||
amount_total = self.amount_untaxed + self.amount_tax
|
||||
if self.discount_type == 'fixed':
|
||||
self.discount_percentage = (self.discount / amount_total) * 100
|
||||
elif self.discount_type == 'percentage':
|
||||
self.discount = amount_total * self.discount_percentage / 100
|
||||
|
||||
@api.onchange('discount', 'discount_percentage', 'discount_type')
|
||||
def onchange_discount(self):
|
||||
amount_total = self.amount_untaxed + self.amount_tax
|
||||
if self.discount:
|
||||
self.discount_percentage = (self.discount / amount_total) * 100
|
||||
if self.discount_percentage:
|
||||
self.discount = amount_total * self.discount_percentage / 100
|
||||
|
||||
@api.multi
|
||||
def _find_batch(self, product, qty, location, picking):
|
||||
_logger.info("\n\n***** Product :%s, Quantity :%s Location :%s\n*****",product,qty,location)
|
||||
lot_objs = self.env['stock.production.lot'].search([('product_id','=',product.id),('life_date','>=',str(fields.datetime.now()))])
|
||||
_logger.info('\n *** Searched Lot Objects:%s \n',lot_objs)
|
||||
if any(lot_objs):
|
||||
#Sort losts based on the expiry date FEFO(First Expiry First Out)
|
||||
lot_objs = list(lot_objs)
|
||||
sorted_lot_list = sorted(lot_objs, key=lambda l: l.life_date)
|
||||
_logger.info('\n *** Sorted based on FEFO :%s \n',sorted_lot_list)
|
||||
done_qty = qty
|
||||
res_lot_ids = []
|
||||
lot_ids_for_query = tuple([lot.id for lot in sorted_lot_list])
|
||||
self._cr.execute("SELECT SUM(qty) FROM stock_quant WHERE lot_id IN %s and location_id=%s",(lot_ids_for_query,location.id,))
|
||||
qry_rslt = self._cr.fetchall()
|
||||
available_qty = qry_rslt[0] and qry_rslt[0][0] or 0
|
||||
if available_qty >= qty:
|
||||
for lot_obj in sorted_lot_list:
|
||||
quants = lot_obj.quant_ids.filtered(lambda q: q.location_id == location)
|
||||
for quant in quants:
|
||||
if done_qty >= 0:
|
||||
res_lot_ids.append(lot_obj)
|
||||
done_qty = done_qty - quant.qty
|
||||
return res_lot_ids
|
||||
else:
|
||||
message = ("<b>Auto validation Failed</b> <br/> <b>Reason:</b> There are not enough stock available for <a href=# data-oe-model=product.product data-oe-id=%d>%s</a> product on <a href=# data-oe-model=stock.location data-oe-id=%d>%s</a> Location") % (product.id,product.name,location.id,location.name)
|
||||
picking.message_post(body=message)
|
||||
else:
|
||||
message = ("<b>Auto validation Failed</b> <br/> <b>Reason:</b> There are no Batches/Serial no's available for <a href=# data-oe-model=product.product data-oe-id=%d>%s</a> product") % (product.id,product.name)
|
||||
picking.message_post(body=message)
|
||||
return False
|
||||
|
||||
@api.multi
|
||||
def action_move_create(self):
|
||||
#This method is overriden to pass the Discount Journal Entry.
|
||||
""" Creates invoice related analytics and financial move lines """
|
||||
account_move = self.env['account.move']
|
||||
|
||||
for inv in self:
|
||||
if not inv.journal_id.sequence_id:
|
||||
raise UserError(_('Please define sequence on the journal related to this invoice.'))
|
||||
if not inv.invoice_line_ids:
|
||||
raise UserError(_('Please create some invoice lines.'))
|
||||
if inv.move_id:
|
||||
continue
|
||||
|
||||
ctx = dict(self._context, lang=inv.partner_id.lang)
|
||||
|
||||
if not inv.date_invoice:
|
||||
inv.with_context(ctx).write({'date_invoice': fields.Date.context_today(self)})
|
||||
company_currency = inv.company_id.currency_id
|
||||
|
||||
# create move lines (one per invoice line + eventual taxes and analytic lines)
|
||||
iml = inv.invoice_line_move_line_get()
|
||||
iml += inv.tax_line_move_line_get()
|
||||
|
||||
diff_currency = inv.currency_id != company_currency
|
||||
# create one move line for the total and possibly adjust the other lines amount
|
||||
total, total_currency, iml = inv.with_context(ctx).compute_invoice_totals(company_currency, iml)
|
||||
|
||||
name = inv.name or '/'
|
||||
if inv.payment_term_id:
|
||||
totlines = inv.with_context(ctx).payment_term_id.with_context(currency_id=company_currency.id).compute(total, inv.date_invoice)[0]
|
||||
res_amount_currency = total_currency
|
||||
ctx['date'] = inv._get_currency_rate_date()
|
||||
for i, t in enumerate(totlines):
|
||||
if inv.currency_id != company_currency:
|
||||
amount_currency = company_currency.with_context(ctx).compute(t[1], inv.currency_id)
|
||||
else:
|
||||
amount_currency = False
|
||||
|
||||
# last line: add the diff
|
||||
res_amount_currency -= amount_currency or 0
|
||||
if i + 1 == len(totlines):
|
||||
amount_currency += res_amount_currency
|
||||
|
||||
iml.append({
|
||||
'type': 'dest',
|
||||
'name': name,
|
||||
'price': t[1],
|
||||
'account_id': inv.account_id.id,
|
||||
'date_maturity': t[0],
|
||||
'amount_currency': diff_currency and amount_currency,
|
||||
'currency_id': diff_currency and inv.currency_id.id,
|
||||
'invoice_id': inv.id
|
||||
})
|
||||
else:
|
||||
iml.append({
|
||||
'type': 'dest',
|
||||
'name': name,
|
||||
'price': total,
|
||||
'account_id': inv.account_id.id,
|
||||
'date_maturity': inv.date_due,
|
||||
'amount_currency': diff_currency and total_currency,
|
||||
'currency_id': diff_currency and inv.currency_id.id,
|
||||
'invoice_id': inv.id
|
||||
})
|
||||
part = self.env['res.partner']._find_accounting_partner(inv.partner_id)
|
||||
line = [(0, 0, self.line_get_convert(l, part.id)) for l in iml]
|
||||
line = inv.group_lines(iml, line)
|
||||
|
||||
journal = inv.journal_id.with_context(ctx)
|
||||
line = inv.finalize_invoice_move_lines(line)
|
||||
date = inv.date or inv.date_invoice
|
||||
move_vals = {
|
||||
'ref': inv.reference,
|
||||
'line_ids': line,
|
||||
'journal_id': journal.id,
|
||||
'date': date,
|
||||
'narration': inv.comment,
|
||||
}
|
||||
ctx['company_id'] = inv.company_id.id
|
||||
ctx['invoice'] = inv
|
||||
ctx_nolang = ctx.copy()
|
||||
ctx_nolang.pop('lang', None)
|
||||
move = account_move.with_context(ctx_nolang).create(move_vals)
|
||||
#=============Customized code starts=========
|
||||
if inv.discount:
|
||||
if inv.type == 'out_refund':
|
||||
move_line = move.line_ids.filtered(lambda l:l.name==inv.name)
|
||||
move_line.credit -= inv.discount
|
||||
move_line_vals = {
|
||||
'name':'Discount',
|
||||
'company_id':move.company_id.id,
|
||||
'account_id':inv.disc_acc_id.id,
|
||||
'credit':inv.discount,
|
||||
'date_maturity':date,
|
||||
'currency_id': diff_currency and inv.currency_id.id,
|
||||
'invoice_id': inv.id,
|
||||
'partner_id':move_line.partner_id.id,
|
||||
'move_id':move.id,
|
||||
}
|
||||
self.env['account.move.line'].create(move_line_vals)
|
||||
|
||||
else:
|
||||
move_line = move.line_ids.filtered(lambda l:l.name=='/')
|
||||
move_line.debit -= inv.discount
|
||||
move_line_vals = {
|
||||
'name':'Discount',
|
||||
'company_id':move.company_id.id,
|
||||
'account_id':inv.disc_acc_id.id,
|
||||
'debit':inv.discount,
|
||||
'date_maturity':date,
|
||||
'currency_id': diff_currency and inv.currency_id.id,
|
||||
'invoice_id': inv.id,
|
||||
'partner_id':move_line.partner_id.id,
|
||||
'move_id':move.id,
|
||||
}
|
||||
self.env['account.move.line'].create(move_line_vals)
|
||||
#===========Customized code ends=============
|
||||
# Pass invoice in context in method post: used if you want to get the same
|
||||
# account move reference when creating the same invoice after a cancelled one:
|
||||
move.post()
|
||||
# make the invoice point to that move
|
||||
vals = {
|
||||
'move_id': move.id,
|
||||
'date': date,
|
||||
'move_name': move.name,
|
||||
}
|
||||
inv.with_context(ctx).write(vals)
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def _prepare_refund(self, invoice, date_invoice=None, date=None, description=None, journal_id=None):
|
||||
""" Prepare the dict of values to create the new refund from the invoice.
|
||||
This method may be overridden to implement custom
|
||||
refund generation (making sure to call super() to establish
|
||||
a clean extension chain).
|
||||
|
||||
:param record invoice: invoice to refund
|
||||
:param string date_invoice: refund creation date from the wizard
|
||||
:param integer date: force date from the wizard
|
||||
:param string description: description of the refund from the wizard
|
||||
:param integer journal_id: account.journal from the wizard
|
||||
:return: dict of value to create() the refund
|
||||
"""
|
||||
values = {}
|
||||
for field in self._get_refund_copy_fields():
|
||||
if invoice._fields[field].type == 'many2one':
|
||||
values[field] = invoice[field].id
|
||||
else:
|
||||
values[field] = invoice[field] or False
|
||||
|
||||
values['invoice_line_ids'] = self._refund_cleanup_lines(invoice.invoice_line_ids)
|
||||
tax_lines = invoice.tax_line_ids
|
||||
taxes_to_change = {
|
||||
line.tax_id.id: line.tax_id.refund_account_id.id
|
||||
for line in tax_lines.filtered(lambda l: l.tax_id.refund_account_id != l.tax_id.account_id)
|
||||
}
|
||||
cleaned_tax_lines = self._refund_cleanup_lines(tax_lines)
|
||||
values['tax_line_ids'] = self._refund_tax_lines_account_change(cleaned_tax_lines, taxes_to_change)
|
||||
|
||||
if journal_id:
|
||||
journal = self.env['account.journal'].browse(journal_id)
|
||||
elif invoice['type'] == 'in_invoice':
|
||||
journal = self.env['account.journal'].search([('type', '=', 'purchase')], limit=1)
|
||||
else:
|
||||
journal = self.env['account.journal'].search([('type', '=', 'sale')], limit=1)
|
||||
values['journal_id'] = journal.id
|
||||
|
||||
values['type'] = TYPE2REFUND[invoice['type']]
|
||||
values['date_invoice'] = date_invoice or fields.Date.context_today(invoice)
|
||||
values['state'] = 'draft'
|
||||
values['number'] = False
|
||||
values['origin'] = invoice.number
|
||||
values['payment_term_id'] = False
|
||||
values['refund_invoice_id'] = invoice.id
|
||||
#=============Customized code starts========= Added Custom discount fields in refund
|
||||
values['discount_type'] = invoice.discount_type
|
||||
values['discount'] = invoice.discount
|
||||
values['discount_percentage'] = invoice.discount_percentage
|
||||
values['disc_acc_id'] = invoice.disc_acc_id.id
|
||||
#===========Customized code ends=============
|
||||
|
||||
if date:
|
||||
values['date'] = date
|
||||
if description:
|
||||
values['name'] = description
|
||||
return values
|
||||
|
BIN
bahmni-addons/bahmni_account/models/account_invoice.pyc
Normal file
BIN
bahmni-addons/bahmni_account/models/account_invoice.pyc
Normal file
Binary file not shown.
43
bahmni-addons/bahmni_account/models/account_invoice_line.py
Normal file
43
bahmni-addons/bahmni_account/models/account_invoice_line.py
Normal file
@ -0,0 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, api, fields
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = 'account.invoice.line'
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
'''This method is overridden to update discount amount in invoice,
|
||||
when invoice is getting created from sale order, and discount type selected in sale order is percentage.
|
||||
Since, discount amount in readonly field and it gets updated by onchange method, which won't get called when invoice is created from backend.'''
|
||||
if vals.get('invoice_id'):
|
||||
invoice_obj = self.env['account.invoice'].browse(vals.get('invoice_id'))
|
||||
amount_untaxed = 0.0
|
||||
amount_tax = 0.0
|
||||
# calculating total from already created invoice lines.
|
||||
for ln in invoice_obj.invoice_line_ids:
|
||||
amount_untaxed += ln.price_subtotal
|
||||
taxes = ln.invoice_line_tax_ids.compute_all(ln.price_subtotal, invoice_obj.currency_id,
|
||||
ln.quantity, product=ln.product_id,
|
||||
partner=invoice_obj.partner_shipping_id)
|
||||
amount_tax += sum(t.get('amount', 0.0) for t in taxes.get('taxes', []))
|
||||
if vals.get('invoice_line_tax_ids'):
|
||||
price_unit = vals.get('price_unit') * vals.get('quantity')
|
||||
if vals.get('discount'):
|
||||
price_unit = price_unit * (1 - vals['discount']/100)
|
||||
amount_untaxed += price_unit
|
||||
tax_ids = []
|
||||
if len(vals['invoice_line_tax_ids'][0]) == 3:
|
||||
tax_ids = vals['invoice_line_tax_ids'][0][2]
|
||||
elif len(vals['invoice_line_tax_ids'][0]) == 1:
|
||||
tax_ids = vals['invoice_line_tax_ids'][0]
|
||||
tax_obj = self.env['account.tax'].browse(tax_ids)
|
||||
taxes = tax_obj.compute_all(price_unit, invoice_obj.currency_id,
|
||||
vals.get('quantity'), product=vals.get('product_id'),
|
||||
partner=invoice_obj.partner_id)
|
||||
amount_tax += sum(t.get('amount', 0.0) for t in taxes.get('taxes', []))
|
||||
if invoice_obj.discount_type == 'percentage':
|
||||
discount_amount = (invoice_obj.currency_id.round(amount_untaxed) +
|
||||
invoice_obj.currency_id.round(amount_tax)) * invoice_obj.discount_percentage / 100
|
||||
invoice_obj.write({'discount': discount_amount})
|
||||
return super(AccountInvoiceLine, self).create(vals)
|
BIN
bahmni-addons/bahmni_account/models/account_invoice_line.pyc
Normal file
BIN
bahmni-addons/bahmni_account/models/account_invoice_line.pyc
Normal file
Binary file not shown.
56
bahmni-addons/bahmni_account/models/account_payment.py
Normal file
56
bahmni-addons/bahmni_account/models/account_payment.py
Normal file
@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from itertools import groupby
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class AccountAbstractPayment(models.AbstractModel):
|
||||
_inherit = 'account.abstract.payment'
|
||||
|
||||
# commented as per Ajeenckya's suggestion, as keeping bank journals in selection, will fulfill the generic way of using payment
|
||||
# journal_id = fields.Many2one('account.journal', string='Payment Journal', required=True,
|
||||
# domain=[('type', '=', 'cash')])
|
||||
|
||||
|
||||
class AccountPayment(models.Model):
|
||||
_inherit = 'account.payment'
|
||||
|
||||
@api.onchange('partner_id', 'amount')
|
||||
def _calculate_balances(self):
|
||||
if(self.state != 'posted'):
|
||||
partner = self.partner_id
|
||||
balance = partner.credit or partner.debit
|
||||
self.balance_before_pay = balance
|
||||
self.total_balance = balance - self.amount
|
||||
|
||||
@api.onchange('invoice_ids')
|
||||
def onchange_partner_id(self):
|
||||
if self.invoice_ids:
|
||||
bill_amount = 0
|
||||
for inv in self.invoice_ids:
|
||||
bill_amount += inv.amount_total
|
||||
self.bill_amount = bill_amount
|
||||
|
||||
@api.onchange('payment_type')
|
||||
def _onchange_payment_type(self):
|
||||
if not self.invoice_ids:
|
||||
# Set default partner type for the payment type
|
||||
if self.payment_type == 'inbound':
|
||||
self.partner_type = 'customer'
|
||||
elif self.payment_type == 'outbound':
|
||||
self.partner_type = 'supplier'
|
||||
else:
|
||||
self.partner_type = False
|
||||
# Set payment method domain
|
||||
res = self._onchange_journal()
|
||||
if not res.get('domain', {}):
|
||||
res['domain'] = {}
|
||||
res['domain']['journal_id'] = self.payment_type == 'inbound' and [('at_least_one_inbound', '=', True)] or self.payment_type == 'outbound' and [('at_least_one_outbound', '=', True)] or []
|
||||
#res['domain']['journal_id'].append(('type', '=', 'cash'))
|
||||
return res
|
||||
|
||||
balance_before_pay = fields.Float(compute=_calculate_balances,
|
||||
string="Balance before pay")
|
||||
total_balance = fields.Float(compute=_calculate_balances,
|
||||
string="Total Balance")
|
||||
invoice_id = fields.Many2one('account.invoice', string='Invoice')
|
||||
bill_amount = fields.Float(string="Bill Amount")
|
BIN
bahmni-addons/bahmni_account/models/account_payment.pyc
Normal file
BIN
bahmni-addons/bahmni_account/models/account_payment.pyc
Normal file
Binary file not shown.
8
bahmni-addons/bahmni_account/models/res_company.py
Normal file
8
bahmni-addons/bahmni_account/models/res_company.py
Normal file
@ -0,0 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
round_off_by = fields.Float(string="Round off by")
|
BIN
bahmni-addons/bahmni_account/models/res_company.pyc
Normal file
BIN
bahmni-addons/bahmni_account/models/res_company.pyc
Normal file
Binary file not shown.
8
bahmni-addons/bahmni_account/models/res_partner.py
Normal file
8
bahmni-addons/bahmni_account/models/res_partner.py
Normal file
@ -0,0 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
initials = fields.Char(string="Initials")
|
15
bahmni-addons/bahmni_account/models/rounding_off.py
Normal file
15
bahmni-addons/bahmni_account/models/rounding_off.py
Normal file
@ -0,0 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class RoundingOff(models.Model):
|
||||
_name = 'rounding.off'
|
||||
|
||||
def round_off_value_to_nearest(self, value):
|
||||
round_off_by = self.env['ir.values'].get_default('sale.config.settings', 'round_off_by')
|
||||
if(round_off_by > 0):
|
||||
half_round_off_by = round_off_by / 2.0
|
||||
remainder = value % round_off_by
|
||||
return -remainder if remainder < half_round_off_by\
|
||||
else round_off_by - remainder
|
||||
return 0
|
BIN
bahmni-addons/bahmni_account/models/rounding_off.pyc
Normal file
BIN
bahmni-addons/bahmni_account/models/rounding_off.pyc
Normal file
Binary file not shown.
3
bahmni-addons/bahmni_account/report/__init__.py
Normal file
3
bahmni-addons/bahmni_account/report/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import account_count_report
|
||||
import account_report
|
BIN
bahmni-addons/bahmni_account/report/__init__.pyc
Normal file
BIN
bahmni-addons/bahmni_account/report/__init__.pyc
Normal file
Binary file not shown.
35
bahmni-addons/bahmni_account/report/account_count_report.py
Normal file
35
bahmni-addons/bahmni_account/report/account_count_report.py
Normal file
@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields, api
|
||||
from odoo.tools import drop_view_if_exists
|
||||
from odoo.exceptions import Warning
|
||||
|
||||
|
||||
class AccountCountReport(models.Model):
|
||||
_name = 'account.count.report'
|
||||
_auto = False
|
||||
_description = "Count of account heads in sale orders over a period"
|
||||
|
||||
count = fields.Integer(string="Count", readonly=True)
|
||||
date = fields.Date(string="Date", readonly=True)
|
||||
account_id = fields.Many2one('account.account', string="Account")
|
||||
|
||||
@api.model_cr
|
||||
def init(self):
|
||||
drop_view_if_exists(self.env.cr, 'account_count_report')
|
||||
self.env.cr.execute("""
|
||||
create or replace view account_count_report as (
|
||||
select
|
||||
concat(ail.account_id, '_', ai.date_invoice) as id,
|
||||
ai.date_invoice as date,
|
||||
ail.account_id as account_id,
|
||||
count(*) as count
|
||||
from account_invoice ai, account_invoice_line ail
|
||||
where
|
||||
ail.invoice_id = ai.id
|
||||
and ai.type != 'out_refund'
|
||||
group by ail.account_id, ai.date_invoice
|
||||
)""")
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
raise Warning('You cannot delete any record!')
|
BIN
bahmni-addons/bahmni_account/report/account_count_report.pyc
Normal file
BIN
bahmni-addons/bahmni_account/report/account_count_report.pyc
Normal file
Binary file not shown.
71
bahmni-addons/bahmni_account/report/account_count_report.xml
Normal file
71
bahmni-addons/bahmni_account/report/account_count_report.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_account_count_report_tree" model="ir.ui.view">
|
||||
<field name="name">account.count.report.tree</field>
|
||||
<field name="model">account.count.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Accounts Report">
|
||||
<field name="date"/>
|
||||
<field name="account_id"/>
|
||||
<field name="count"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_count_report_filter" model="ir.ui.view">
|
||||
<field name="name">account.count.report.filter</field>
|
||||
<field name="model">account.count.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Accounts Report">
|
||||
<field name="account_id"/>
|
||||
|
||||
<filter string="Last 30 Days" name="filter_month"
|
||||
domain="[
|
||||
['date', '<=', context_today().strftime('%%Y-%%m-%%d')],
|
||||
['date', '>=', (context_today() - datetime.timedelta(30)).strftime('%%Y-%%m-%%d')]
|
||||
]" />
|
||||
|
||||
<filter string="Today" name="filter_today"
|
||||
domain="[('date', '=', context_today().strftime('%%Y-%%m-%%d'))]"/>
|
||||
|
||||
<group string="Group By...">
|
||||
<filter string="Account" name="groupby_account_head"
|
||||
icon="terp-go-month" domain="[]" context="{'group_by':'account_id'}"/>
|
||||
<filter string="Date" name="groupby_date_head"
|
||||
icon="terp-go-month" domain="[]" context="{'group_by':'date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_search_account_count_reports" model="ir.actions.act_window">
|
||||
<field name="name">Accounts Count Report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.count.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_account_count_report_tree"/>
|
||||
<field name="search_view_id" ref="view_account_count_report_filter"/>
|
||||
<field name="context">{}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_search_account_count_reports"
|
||||
id="menu_action_search_account_count_reports"
|
||||
parent="account.menu_finance_reports" groups="account.group_account_user" />
|
||||
|
||||
<!--<record id="filter_account_count_report_by_account_id" model="ir.filters">
|
||||
<field name="name">Required Accounts Only</field>
|
||||
<field name="model_id">account.count.report</field>
|
||||
<field name="is_default">1</field>
|
||||
<field name="user_id"></field>
|
||||
<field name="domain">
|
||||
[ '|', '|', '|',
|
||||
['account_id', 'ilike', 'ECG'],
|
||||
['account_id', 'ilike', 'X-Ray'],
|
||||
['account_id', 'ilike', 'MTP'],
|
||||
['account_id', 'ilike', 'Sonography']
|
||||
]
|
||||
</field>
|
||||
</record>-->
|
||||
</odoo>
|
76
bahmni-addons/bahmni_account/report/account_report.py
Normal file
76
bahmni-addons/bahmni_account/report/account_report.py
Normal file
@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields, api
|
||||
from odoo.tools import drop_view_if_exists
|
||||
|
||||
|
||||
class AccountReport(models.Model):
|
||||
_name = 'account.report'
|
||||
_description = "Account reports for actual & received amount"
|
||||
_auto = False
|
||||
|
||||
actual_amount = fields.Integer(string="Expenses")
|
||||
amount_received = fields.Integer(string="Collections")
|
||||
date = fields.Date(string="Date")
|
||||
account_id = fields.Many2one('account.account', string="Account Head")
|
||||
|
||||
@api.model_cr
|
||||
def init(self):
|
||||
drop_view_if_exists(self.env.cr, 'account_report')
|
||||
self.env.cr.execute("""
|
||||
create or replace view account_report as (
|
||||
(select id,date,account_id, sum(actual_amount) as actual_amount,sum(amount_received) as amount_received
|
||||
from (
|
||||
SELECT
|
||||
pg_catalog.concat(ail.account_id, '_', ai.date_invoice, '_', ai.type) AS id,ai.id as invoice_id,
|
||||
ai.date_invoice AS date,
|
||||
ail.account_id,
|
||||
CASE
|
||||
WHEN ai.type = 'out_refund' THEN 0
|
||||
ELSE sum(ail.price_subtotal)
|
||||
END AS actual_amount,
|
||||
CASE
|
||||
WHEN ai.type = 'out_refund' THEN sum(
|
||||
(-ail.price_subtotal) * (ai.amount_total / (ai.amount_tax + ai.amount_untaxed)))
|
||||
ELSE sum(ail.price_subtotal * (ai.amount_total / (ai.amount_tax + ai.amount_untaxed)))
|
||||
END AS amount_received
|
||||
FROM account_invoice ai, account_invoice_line ail
|
||||
WHERE ail.invoice_id = ai.id AND (ai.amount_tax + ai.amount_untaxed) <> 0 AND state = 'paid'
|
||||
GROUP BY ail.account_id, ai.date_invoice, ai.type, ai.id
|
||||
UNION
|
||||
SELECT
|
||||
pg_catalog.concat(ail.account_id, '_', ai.date_invoice, '_', ai.type) AS id,ai.id as invoice_id,
|
||||
ai.date_invoice AS date,
|
||||
ail.account_id,
|
||||
CASE
|
||||
WHEN ai.type = 'out_refund' THEN 0
|
||||
ELSE max(ai.amount_total)
|
||||
END AS actual_amount,
|
||||
CASE
|
||||
WHEN ai.type = 'out_refund' THEN max(ai.amount_total) * -1
|
||||
ELSE max(ai.amount_total)
|
||||
END AS amount_received
|
||||
FROM account_invoice ai, account_invoice_line ail
|
||||
WHERE ail.invoice_id = ai.id AND (ai.amount_tax + ai.amount_untaxed) = 0 AND state = 'paid'
|
||||
and ail.account_id not in
|
||||
(select id from account_account where name in ('FINE','Discount','Overcharge'))
|
||||
GROUP BY ail.account_id, ai.date_invoice, ai.type,ai.id
|
||||
UNION
|
||||
SELECT
|
||||
pg_catalog.concat(ail.account_id, '_', ai.date_invoice, '_', ai.type) AS id,ai.id as invoice_id,
|
||||
ai.date_invoice AS date,
|
||||
ail.account_id,
|
||||
CASE
|
||||
WHEN ai.type = 'out_refund' THEN 0
|
||||
ELSE sum(ai.amount_total)
|
||||
END AS actual_amount,
|
||||
CASE
|
||||
WHEN ai.type = 'out_refund' THEN sum(-ai.amount_total)
|
||||
ELSE sum(ai.amount_total)
|
||||
END AS amount_received
|
||||
FROM account_invoice ai, account_invoice_line ail
|
||||
WHERE ail.invoice_id = ai.id AND (ai.amount_tax + ai.amount_untaxed) = 0 AND state = 'paid'
|
||||
and ail.account_id in
|
||||
(select id from account_account where name in ('FINE','Discount','Overcharge'))
|
||||
GROUP BY ail.account_id, ai.date_invoice, ai.type,ai.id
|
||||
) as r group by id,date,account_id)
|
||||
)""")
|
BIN
bahmni-addons/bahmni_account/report/account_report.pyc
Normal file
BIN
bahmni-addons/bahmni_account/report/account_report.pyc
Normal file
Binary file not shown.
59
bahmni-addons/bahmni_account/report/account_report.xml
Normal file
59
bahmni-addons/bahmni_account/report/account_report.xml
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_account_report_tree" model="ir.ui.view">
|
||||
<field name="name">account.report.tree</field>
|
||||
<field name="model">account.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Accounts Report">
|
||||
<field name="date"/>
|
||||
<field name="account_id"/>
|
||||
<field name="amount_received" sum="Total Collections"/>
|
||||
<field name="actual_amount" sum="Total Expense"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_report_filter" model="ir.ui.view">
|
||||
<field name="name">account.report.filter</field>
|
||||
<field name="model">account.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Accounts Report">
|
||||
<field name="account_id"/>
|
||||
|
||||
<filter string="Last 30 Days" name="filter_month"
|
||||
domain="[
|
||||
['date', '<=', context_today().strftime('%%Y-%%m-%%d')],
|
||||
['date', '>=', (context_today() - datetime.timedelta(30)).strftime('%%Y-%%m-%%d')]
|
||||
]" />
|
||||
|
||||
<filter string="Today" name="filter_today"
|
||||
domain="[('date', '=', context_today().strftime('%%Y-%%m-%%d'))]"/>
|
||||
|
||||
<group string="Group By...">
|
||||
<filter string="Account" name="groupby_account_head"
|
||||
icon="terp-go-month" domain="[]" context="{'group_by':'account_id'}"/>
|
||||
<filter string="Date" name="groupby_date_head"
|
||||
icon="terp-go-month" domain="[]" context="{'group_by':'date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_search_account_reports" model="ir.actions.act_window">
|
||||
<field name="name">Account Report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_account_report_tree"/>
|
||||
<field name="search_view_id" ref="view_account_report_filter"/>
|
||||
<field name="context">{}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_search_account_reports"
|
||||
id="menu_action_search_account_reports"
|
||||
parent="account.menu_finance_reports" groups="account.group_account_user"
|
||||
sequence="3"/>
|
||||
|
||||
</odoo>
|
168
bahmni-addons/bahmni_account/report/report_invoice_inherit.xml
Normal file
168
bahmni-addons/bahmni_account/report/report_invoice_inherit.xml
Normal file
@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<template id="account.report_invoice_document">
|
||||
<t t-call="report.external_layout">
|
||||
<t t-set="o" t-value="o.with_context({'lang':o.partner_id.lang})" />
|
||||
<div class="page">
|
||||
<div class="row">
|
||||
<div name="invoice_address" class="col-xs-5 col-xs-offset-7">
|
||||
<address t-field="o.partner_id"
|
||||
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}' />
|
||||
<span t-if="o.partner_id.vat">TIN: <span t-field="o.partner_id.vat"/></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>
|
||||
<span t-if="o.type == 'out_invoice' and (o.state == 'open' or o.state == 'paid')">Invoice</span>
|
||||
<span t-if="o.type == 'out_invoice' and o.state == 'proforma2'">PRO-FORMA</span>
|
||||
<span t-if="o.type == 'out_invoice' and o.state == 'draft'">Draft Invoice</span>
|
||||
<span t-if="o.type == 'out_invoice' and o.state == 'cancel'">Cancelled Invoice</span>
|
||||
<span t-if="o.type == 'out_refund'">Refund</span>
|
||||
<span t-if="o.type == 'in_refund'">Vendor Refund</span>
|
||||
<span t-if="o.type == 'in_invoice'">Vendor Bill</span>
|
||||
<span t-field="o.number"/>
|
||||
</h2>
|
||||
|
||||
<div class="row mt32 mb32">
|
||||
<div class="col-xs-2" t-if="o.name">
|
||||
<strong>Description:</strong>
|
||||
<p t-field="o.name"/>
|
||||
</div>
|
||||
<div class="col-xs-2" t-if="o.date_invoice">
|
||||
<strong>Invoice Date:</strong>
|
||||
<p t-field="o.date_invoice"/>
|
||||
</div>
|
||||
<div class="col-xs-2" t-if="o.date_due and o.type == 'out_invoice' and (o.state == 'open' or o.state == 'paid')">
|
||||
<strong>Due Date:</strong>
|
||||
<p t-field="o.date_due"/>
|
||||
</div>
|
||||
<div class="col-xs-2" t-if="o.origin">
|
||||
<strong>Source:</strong>
|
||||
<p t-field="o.origin"/>
|
||||
</div>
|
||||
<div class="col-xs-2" t-if="o.partner_id.ref">
|
||||
<strong>Customer Code:</strong>
|
||||
<p t-field="o.partner_id.ref"/>
|
||||
</div>
|
||||
<div name="reference" class="col-xs-2" t-if="o.reference">
|
||||
<strong>Reference:</strong>
|
||||
<p t-field="o.reference"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Is there a discount on at least one line? -->
|
||||
<t t-set="display_discount" t-value="any([l.discount for l in o.invoice_line_ids])"/>
|
||||
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<th class="hidden">Source Document</th>
|
||||
<th class="text-right">Quantity</th>
|
||||
<th class="text-right">Batch No</th>
|
||||
<th class="text-right">Expiry Date</th>
|
||||
<th class="text-right">Unit Price</th>
|
||||
<th t-if="display_discount" class="text-right">Disc.(%)</th>
|
||||
<th class="text-right">Taxes</th>
|
||||
<th class="text-right">Tax Excluded Price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="invoice_tbody">
|
||||
<tr t-foreach="o.invoice_line_ids" t-as="l">
|
||||
<td><span t-field="l.name"/></td>
|
||||
<td class="hidden"><span t-field="l.origin"/></td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.quantity"/>
|
||||
<span t-field="l.uom_id" groups="product.group_uom"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.lot_id.name"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.expiry_date"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.price_unit"/>
|
||||
</td>
|
||||
<td t-if="display_discount" class="text-right">
|
||||
<span t-field="l.discount"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-esc="', '.join(map(lambda x: (x.description or x.name), l.invoice_line_tax_ids))"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.price_subtotal"
|
||||
t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-4 pull-right">
|
||||
<table class="table table-condensed">
|
||||
<tr class="border-black">
|
||||
<td><strong>Subtotal</strong></td>
|
||||
<td class="text-right">
|
||||
<span t-field="o.amount_untaxed" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<t t-foreach="o._get_tax_amount_by_group()" t-as="amount_by_group">
|
||||
<tr>
|
||||
<td><span t-esc="amount_by_group[0] if len(o.tax_line_ids) > 1 else (o.tax_line_ids.tax_id.description or o.tax_line_ids.tax_id.name)"/></td>
|
||||
<td class="text-right">
|
||||
<span t-esc="amount_by_group[2]"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr class="border-black">
|
||||
<td><strong>Total</strong></td>
|
||||
<td class="text-right">
|
||||
<span t-field="o.amount_total" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DO NOT REMOVE THIS TABLE. MANDATORY IN SOME COUNTRIES -->
|
||||
<div class="row" t-if="len(o.tax_line_ids) > 0">
|
||||
<div class="col-xs-6">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tax</th>
|
||||
<th class="text-right">Base</th>
|
||||
<th class="text-right">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="o.tax_line_ids" t-as="t">
|
||||
<td><span t-field="t.tax_id.description"/></td>
|
||||
<td class="text-right">
|
||||
<span t-field="t.base" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="t.amount" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p t-if="o.comment">
|
||||
<strong>Comment:</strong>
|
||||
<span t-field="o.comment"/>
|
||||
</p>
|
||||
<p t-if="o.payment_term_id">
|
||||
<span t-field="o.payment_term_id.note"/>
|
||||
</p>
|
||||
<p t-if="o.fiscal_position_id.note">
|
||||
<strong>Fiscal Position Remark:</strong>
|
||||
<span t-field="o.fiscal_position_id.note"/>
|
||||
</p>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
@ -0,0 +1,4 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_account_count_report_account_user,Account Count Report Account User,model_account_count_report,account.group_account_user,1,1,1,0
|
||||
access_rounding_off,access_rounding_off,model_rounding_off,,1,1,1,1
|
||||
access_account_report,access_account_report,model_account_report,,1,1,1,1
|
|
BIN
bahmni-addons/bahmni_account/static/description/icon.png
Normal file
BIN
bahmni-addons/bahmni_account/static/description/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,20 @@
|
||||
/* css code for sale order form footer */
|
||||
.footer_label{
|
||||
padding-right:0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.footer_label > label:after{
|
||||
content: ": "
|
||||
}
|
||||
|
||||
|
||||
.footer_field{
|
||||
padding-right:0px;
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
.footer_text_bold{
|
||||
font-size: 1.3em;
|
||||
padding-right: 80px;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="inherit_view_account_config_settings" model="ir.ui.view">
|
||||
<field name="name">inherit.view.account.config.settings</field>
|
||||
<field name="model">account.config.settings</field>
|
||||
<field name="inherit_id" ref="account.view_account_config_settings"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//separator[@name='analytic_account']" position="before">
|
||||
<group>
|
||||
<label for="round_off_by"/>
|
||||
<field name="round_off_by" nolabel="1"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
186
bahmni-addons/bahmni_account/views/account_invoice_view.xml
Normal file
186
bahmni-addons/bahmni_account/views/account_invoice_view.xml
Normal file
@ -0,0 +1,186 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="inherit_invoice_form" model="ir.ui.view">
|
||||
<field name="name">inherit.invoice.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//notebook/page/group" position="replace">
|
||||
<div class="col-xs-5 pull-right text-right" style="padding-right:0px">
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;">
|
||||
<label for="amount_untaxed" />
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height: 28px;">
|
||||
<field name="amount_untaxed"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;">
|
||||
<label for="amount_tax"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height: 28px;">
|
||||
<field name="amount_tax"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;">
|
||||
<label for="discount_type"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height: 28px;">
|
||||
<field name="discount_type" required="1"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;">
|
||||
<label for="round_off_amount"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height: 28px;">
|
||||
<field name="round_off_amount"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;"
|
||||
attrs="{'invisible': [('discount_type', '!=', 'percentage')]}">
|
||||
<label for="discount_percentage" />
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="white-space:nowrap;padding-right:15px"
|
||||
attrs="{'invisible': [('discount_type', '!=', 'percentage')]}" >
|
||||
<field name="discount_percentage" /> <b style="padding-left:2px">%</b>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height:33px;"
|
||||
attrs="{'invisible': [('discount_type', '=', 'none')]}">
|
||||
<label for="discount" />
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height:33px;"
|
||||
attrs="{'invisible': [('discount_type', '=', 'none')]}">
|
||||
<field name="discount" style="width:100% !important" context="{'readonly_by_pass': True}"
|
||||
attrs="{'readonly': [('discount_type', '=', 'percentage')]}"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label"
|
||||
attrs="{'invisible': [('discount_type', '=', 'none')]}">
|
||||
<label for="disc_acc_id" name="remove_display_prop"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" attrs="{'invisible': [('discount_type', '=', 'none')]}">
|
||||
<field name="disc_acc_id"
|
||||
attrs="{'required': [('discount_type', 'in', ('fixed', 'percentage'))]}"/>
|
||||
</div>
|
||||
<group style="width: 100%; border-top: 1px solid #cacaca;
|
||||
font-weight: bold; white-space:nowrap;">
|
||||
<div class="col-xs-6 oe_right footer_label">
|
||||
<label for="amount_total" style="font-weight:bold"/>
|
||||
<button name="button_dummy" states="draft,sent" string="(update)"
|
||||
type="object" class="oe_edit_only oe_link"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field footer_text_bold" >
|
||||
<field name="amount_total" />
|
||||
</div>
|
||||
</group>
|
||||
<group style="width: 100%; border-top: 1px solid #cacaca;
|
||||
font-weight: bold; white-space:nowrap;">
|
||||
<div class="col-xs-6 oe_right footer_label">
|
||||
<label for="residual" style="font-weight:bold"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field footer_text_bold" >
|
||||
<field name="residual" />
|
||||
</div>
|
||||
</group>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account.action_invoice_tree1" model="ir.actions.act_window">
|
||||
<field name="name">Customer Invoices</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot,graph</field>
|
||||
<field eval="False" name="view_id"/>
|
||||
<field name="domain">[('type','in',('out_invoice', 'out_refund'))]</field>
|
||||
<field name="context">{'type':'out_invoice', 'journal_type': 'sale',
|
||||
'readonly_by_pass': True}
|
||||
</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a customer invoice.
|
||||
</p>
|
||||
<p>
|
||||
Odoo's electronic invoicing allows to ease and fasten the
|
||||
collection of customer payments. Your customer receives the
|
||||
invoice by email and he can pay online and/or import it
|
||||
in his own system.
|
||||
</p>
|
||||
<p>
|
||||
The discussions with your customer are automatically displayed at
|
||||
the bottom of each invoice.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!--Supplier Form-->
|
||||
<record id="inherit_invoice_supplier_form" model="ir.ui.view">
|
||||
<field name="name">inherit.invoice.supplier.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//notebook/page/group" position="replace">
|
||||
<div class="col-xs-5 pull-right text-right" style="padding-right:0px">
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;">
|
||||
<label for="amount_untaxed" />
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height: 28px;">
|
||||
<field name="amount_untaxed"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;">
|
||||
<label for="amount_tax"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height: 28px;">
|
||||
<field name="amount_tax"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;">
|
||||
<label for="discount_type"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height: 28px;">
|
||||
<field name="discount_type" required="1"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;">
|
||||
<label for="round_off_amount"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height: 28px;">
|
||||
<field name="round_off_amount"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height: 28px;"
|
||||
attrs="{'invisible': [('discount_type', '!=', 'percentage')]}">
|
||||
<label for="discount_percentage" />
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="white-space:nowrap;padding-right:15px"
|
||||
attrs="{'invisible': [('discount_type', '!=', 'percentage')]}" >
|
||||
<field name="discount_percentage" /> <b style="padding-left:2px">%</b>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label" style="min-height:33px;"
|
||||
attrs="{'invisible': [('discount_type', '=', 'none')]}">
|
||||
<label for="discount" />
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" style="min-height:33px;"
|
||||
attrs="{'invisible': [('discount_type', '=', 'none')]}">
|
||||
<field name="discount" style="width:100% !important" context="{'readonly_by_pass': True}"
|
||||
attrs="{'readonly': [('discount_type', '=', 'percentage')]}"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_label"
|
||||
attrs="{'invisible': [('discount_type', '=', 'none')]}">
|
||||
<label for="disc_acc_id" name="remove_display_prop"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field" attrs="{'invisible': [('discount_type', '=', 'none')]}">
|
||||
<field name="disc_acc_id"
|
||||
attrs="{'required': [('discount_type', 'in', ('fixed', 'percentage'))]}"/>
|
||||
</div>
|
||||
<group style="width: 100%; border-top: 1px solid #cacaca;
|
||||
font-weight: bold; white-space:nowrap;">
|
||||
<div class="col-xs-6 oe_right footer_label">
|
||||
<label for="amount_total" />
|
||||
<button name="button_dummy" states="draft,sent" string="(update)"
|
||||
type="object" class="oe_edit_only oe_link"/>
|
||||
</div>
|
||||
<div class="col-xs-6 footer_field footer_text_bold" >
|
||||
<field name="amount_total" />
|
||||
</div>
|
||||
</group>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
44
bahmni-addons/bahmni_account/views/account_payment.xml
Normal file
44
bahmni-addons/bahmni_account/views/account_payment.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_account_payment_form_inherit" model="ir.ui.view">
|
||||
<field name="name">view.account.payment.form.inherit</field>
|
||||
<field name="model">account.payment</field>
|
||||
<field name="inherit_id" ref="account.view_account_payment_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='journal_id']" position="before">
|
||||
<field name="balance_before_pay" string="Amount Due"/>
|
||||
<field name="bill_amount"/>
|
||||
<field name="total_balance"/>
|
||||
<field name="invoice_id"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='journal_id']" position="replace">
|
||||
<field name="journal_id" widget="selection"
|
||||
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_register_payment_inherit" model="ir.ui.view">
|
||||
<field name="name">view.register.payment.inherit</field>
|
||||
<field name="model">account.payment</field>
|
||||
<field name="inherit_id" ref="account.view_account_payment_invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//label[@for='amount']" position="before">
|
||||
<field name="balance_before_pay" readonly="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//div[@name='amount_div']" position="after">
|
||||
<field name="bill_amount" readonly="1"/>
|
||||
<field name="total_balance" readonly="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='journal_id']" position="replace">
|
||||
<field name="journal_id" widget="selection"/>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='post']" position="replace">
|
||||
<button string="Validate" name="post" type="object" class="btn-primary"
|
||||
context="{'readonly_by_pass': True}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
13
bahmni-addons/bahmni_account/views/bahmni_account.xml
Normal file
13
bahmni-addons/bahmni_account/views/bahmni_account.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<template id="assets_backend" name="bahmni_account assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/bahmni_account/static/src/css/account_invoice_footer.css"/>
|
||||
<!-- <script type="text/javascript" src="/bahmni_account/static/src/js/sale_order_footer.js"></script-->
|
||||
|
||||
<!-- <script type="text/javascript" src="/account/static/src/js/tour_bank_statement_reconciliation.js"></script> -->
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
3
bahmni-addons/bahmni_atom_feed/__init__.py
Normal file
3
bahmni-addons/bahmni_atom_feed/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import models
|
||||
import wizard
|
30
bahmni-addons/bahmni_atom_feed/__manifest__.py
Normal file
30
bahmni-addons/bahmni_atom_feed/__manifest__.py
Normal file
@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': 'Bahmni Atom Feed',
|
||||
'version': '1.0',
|
||||
'summary': 'Module to sync Bahmni with Odoo',
|
||||