Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Odoo upgrade test #29

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b3e5e23
[Hari] | BAH-3242 | Add. Login api with token based authentication.
Nov 20, 2023
daed6bf
[Hari] | BAH-3299 | Add. Sale Order Creation API with Custom Fields …
Nov 20, 2023
e925e06
[Hari] | BAH-3299 | Update. unwanted files removed
Nov 20, 2023
c2794e6
[Hari] | BAH-3329 | Add. Customer Master API Service with Custom Fiel…
Nov 20, 2023
bd324b3
Revert "[Hari] | BAH-3329 | Add. Customer Master API Service with Cus…
Nov 20, 2023
77e02e3
[Hari] | BAH-3329 | Add. Customer Master API Service with Custom Fiel…
Nov 20, 2023
7051e9f
[]
Nov 21, 2023
05c8800
Revert "[]"
Nov 21, 2023
b6b033b
[Hari] | BAH-3298 | Add. Drug Master API Service with Customized Fiel…
Nov 21, 2023
a0e7861
[Hari] | BAH-3300 | Drug Master API Service with Customized Fields an…
Nov 21, 2023
ef94739
[Hari] | BAH-3301 | Add. Lab Test Creation API Service with Relevant…
Nov 21, 2023
8f63306
[Hari] | BAH-3302 | Lab Panel Creation API Service with Relevant Fiel…
Nov 21, 2023
01b2f86
[Hari] | BAH-3302 | Update. logic updated
Nov 21, 2023
2677a5a
[Hari] | BAH-3303 | Add. Saleable Service Creation API with Custom Fi…
Nov 21, 2023
315c3b3
[Hari] | BAH-3305 | Add. Bahmni_product: Custom Fields and Logic for …
Nov 22, 2023
fba4ad8
[Hari] | BAH-3308 | Add. Bahmni_purchase: Custom Fields and Logic for…
Nov 22, 2023
a361a8b
[Hari] | BAH-3307 | Add. Bahmni_stock : Custom Fields and Logic for P…
Nov 22, 2023
425d413
[Hari] | BAH-3310 | Add. jss_data_import: Implemented Master Data Mig…
Nov 22, 2023
f7a8d6c
[Hari] | Add. Custom Modules for Testing
Nov 23, 2023
7e8ece3
[Parvathy, Rahul] | Add. Custom Modules to image
rahu1ramesh Nov 23, 2023
2864fee
[Rahul] | Add. New Modules
rahu1ramesh Nov 28, 2023
afd2acf
[Hari] | Updated. Customer endpoint method was updated.
Nov 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build_publish_odoo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
branches:
- main
- "release-*"
- "odoo-upgrade-test"
tags:
- "[0-9]+.[0-9]+.[0-9]+"
paths-ignore:
Expand Down
3 changes: 3 additions & 0 deletions bahmni_account/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import models
# ~ from . import report
28 changes: 28 additions & 0 deletions bahmni_account/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- 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'],
'data': [
'views/bahmni_account.xml',
'views/account_invoice_view.xml',
'views/account_config_settings.xml',
'views/company_view.xml',
'views/account_payment.xml',
],
'demo': [],
'qweb': [],
'license': 'LGPL-3',
'installable': True,
'application': True,
'auto_install': False,
}
13 changes: 13 additions & 0 deletions bahmni_account/data/discount_accounts.xml
Original file line number Diff line number Diff line change
@@ -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 changes: 19 additions & 0 deletions bahmni_account/doc/ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -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 changes: 3 additions & 0 deletions bahmni_account/doc/imp_points.txt
Original file line number Diff line number Diff line change
@@ -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 changes: 7 additions & 0 deletions bahmni_account/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from . import rounding_off
from . import account_invoice
from . import account_invoice_line
from . import account_config_settings
from . import res_company
from . import account_payment
14 changes: 14 additions & 0 deletions bahmni_account/models/account_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api


class AccountConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'

round_off_by = fields.Float(string="Round off by", related="company_id.round_off_by")

def set_round_off_by_defaults(self):
return self.env['ir.values'].sudo().set_default(
'res.config.settings', 'round_off_by', self.round_off_by)


287 changes: 287 additions & 0 deletions bahmni_account/models/account_invoice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
# -*- 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.move'

# # overridden this method to deduct discounted amount from total of invoice
@api.depends('invoice_line_ids.price_subtotal','line_ids.tax_line_id.amount',
'currency_id', 'company_id', 'date', 'move_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(line.price_total for line in self.invoice_line_ids) - sum(line.price_subtotal for line in self.invoice_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.move_type in ['in_refund', 'out_refund'] and -1 or 1
self.amount_total_in_currency_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

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

def button_dummy(self):
return self._compute_amount()


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

Loading