mirror of
https://github.com/bringout/odoomates.git
synced 2026-04-26 21:32:06 +02:00
Initial commit: Odoomates Odoo packages (12 packages)
This commit is contained in:
commit
3b38c49bf0
526 changed files with 34983 additions and 0 deletions
|
|
@ -0,0 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import followup_print
|
||||
from . import followup_results
|
||||
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import datetime
|
||||
import time
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class FollowupPrint(models.TransientModel):
|
||||
_name = 'followup.print'
|
||||
_description = 'Print Follow-up & Send Mail to Customers'
|
||||
|
||||
def _get_followup(self):
|
||||
if self.env.context.get('active_model',
|
||||
'ir.ui.menu') == 'followup.followup':
|
||||
return self.env.context.get('active_id', False)
|
||||
company_id = self.env.user.company_id.id
|
||||
followp_id = self.env['followup.followup'].search(
|
||||
[('company_id', '=', company_id)], limit=1)
|
||||
return followp_id or False
|
||||
|
||||
date = fields.Date('Follow-up Sending Date', required=True,
|
||||
help="This field allow you to select a forecast date "
|
||||
"to plan your follow-ups",
|
||||
default=lambda *a: time.strftime('%Y-%m-%d'))
|
||||
followup_id = fields.Many2one('followup.followup', 'Follow-Up',
|
||||
required=True, readonly=True,
|
||||
default=_get_followup)
|
||||
partner_ids = fields.Many2many('followup.stat.by.partner',
|
||||
'partner_stat_rel', 'osv_memory_id',
|
||||
'partner_id', 'Partners', required=True)
|
||||
company_id = fields.Many2one('res.company', readonly=True,
|
||||
related='followup_id.company_id')
|
||||
email_conf = fields.Boolean('Send Email Confirmation')
|
||||
email_subject = fields.Char('Email Subject', size=64,
|
||||
default=_('Invoices Reminder'))
|
||||
partner_lang = fields.Boolean(
|
||||
'Send Email in Partner Language', default=True,
|
||||
help='Do not change message text, if you want to send email in '
|
||||
'partner language, or configure from company')
|
||||
email_body = fields.Text('Email Body', default='')
|
||||
summary = fields.Text('Summary', readonly=True)
|
||||
test_print = fields.Boolean(
|
||||
'Test Print', help='Check if you want to print follow-ups without '
|
||||
'changing follow-up level.')
|
||||
|
||||
def process_partners(self, partner_ids, data):
|
||||
partner_obj = self.env['res.partner']
|
||||
partner_ids_to_print = []
|
||||
nbmanuals = 0
|
||||
manuals = {}
|
||||
nbmails = 0
|
||||
nbunknownmails = 0
|
||||
nbprints = 0
|
||||
resulttext = " "
|
||||
for partner in self.env['followup.stat.by.partner'].browse(
|
||||
partner_ids):
|
||||
if partner.max_followup_id.manual_action:
|
||||
partner_obj.do_partner_manual_action([partner.partner_id.id])
|
||||
nbmanuals = nbmanuals + 1
|
||||
key = partner.partner_id.payment_responsible_id.name or _(
|
||||
"Anybody")
|
||||
if key not in manuals.keys():
|
||||
manuals[key] = 1
|
||||
else:
|
||||
manuals[key] = manuals[key] + 1
|
||||
if partner.max_followup_id.send_email:
|
||||
nbunknownmails += partner.partner_id.do_partner_mail()
|
||||
nbmails += 1
|
||||
if partner.max_followup_id.send_letter:
|
||||
partner_ids_to_print.append(partner.id)
|
||||
nbprints += 1
|
||||
followup_without_lit = \
|
||||
partner.partner_id.latest_followup_level_id_without_lit
|
||||
message = "%s<I> %s </I>%s" % (_("Follow-up letter of "),
|
||||
followup_without_lit.name,
|
||||
_(" will be sent"))
|
||||
partner.partner_id.message_post(body=message)
|
||||
if nbunknownmails == 0:
|
||||
resulttext += str(nbmails) + _(" email(s) sent")
|
||||
else:
|
||||
resulttext += str(nbmails) + _(
|
||||
" email(s) should have been sent, but ") + str(
|
||||
nbunknownmails) + _(
|
||||
" had unknown email address(es)") + "\n <BR/> "
|
||||
resulttext += "<BR/>" + str(nbprints) + _(
|
||||
" letter(s) in report") + " \n <BR/>" + str(nbmanuals) + _(
|
||||
" manual action(s) assigned:")
|
||||
needprinting = False
|
||||
if nbprints > 0:
|
||||
needprinting = True
|
||||
resulttext += "<p align=\"center\">"
|
||||
for item in manuals:
|
||||
resulttext = resulttext + "<li>" + item + ":" + str(
|
||||
manuals[item]) + "\n </li>"
|
||||
resulttext += "</p>"
|
||||
result = {}
|
||||
action = partner_obj.do_partner_print(partner_ids_to_print, data)
|
||||
result['needprinting'] = needprinting
|
||||
result['resulttext'] = resulttext
|
||||
result['action'] = action or {}
|
||||
return result
|
||||
|
||||
def do_update_followup_level(self, to_update, partner_list, date):
|
||||
for id in to_update.keys():
|
||||
if to_update[id]['partner_id'] in partner_list:
|
||||
self.env['account.move.line'].browse([int(id)]).write(
|
||||
{'followup_line_id': to_update[id]['level'],
|
||||
'followup_date': date})
|
||||
|
||||
def clear_manual_actions(self, partner_list):
|
||||
partner_list_ids = [partner.partner_id.id for partner in self.env[
|
||||
'followup.stat.by.partner'].browse(partner_list)]
|
||||
ids = self.env['res.partner'].search(
|
||||
['&', ('id', 'not in', partner_list_ids), '|',
|
||||
('payment_responsible_id', '!=', False),
|
||||
('payment_next_action_date', '!=', False)])
|
||||
|
||||
partners_to_clear = []
|
||||
for part in ids:
|
||||
if not part.unreconciled_aml_ids:
|
||||
partners_to_clear.append(part.id)
|
||||
part.action_done()
|
||||
return len(partners_to_clear)
|
||||
|
||||
def do_process(self):
|
||||
context = dict(self.env.context or {})
|
||||
|
||||
tmp = self._get_partners_followp()
|
||||
partner_list = tmp['partner_ids']
|
||||
to_update = tmp['to_update']
|
||||
date = self.date
|
||||
data = self.read()[0]
|
||||
data['followup_id'] = data['followup_id'][0]
|
||||
|
||||
self.do_update_followup_level(to_update, partner_list, date)
|
||||
restot_context = context.copy()
|
||||
restot = self.with_context(restot_context).process_partners(
|
||||
partner_list, data)
|
||||
context.update(restot_context)
|
||||
nbactionscleared = self.clear_manual_actions(partner_list)
|
||||
if nbactionscleared > 0:
|
||||
restot['resulttext'] = restot['resulttext'] + "<li>" + _(
|
||||
"%s partners have no credits and as such the "
|
||||
"action is cleared") % (str(nbactionscleared)) + "</li>"
|
||||
resource_id = self.env.ref(
|
||||
'om_account_followup.view_om_account_followup_sending_results')
|
||||
context.update({'description': restot['resulttext'],
|
||||
'needprinting': restot['needprinting'],
|
||||
'report_data': restot['action']})
|
||||
return {
|
||||
'name': _('Send Letters and Emails: Actions Summary'),
|
||||
'view_type': 'form',
|
||||
'context': context,
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'followup.sending.results',
|
||||
'views': [(resource_id.id, 'form')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
def _get_msg(self):
|
||||
return self.env.user.company_id.follow_up_msg
|
||||
|
||||
def _get_partners_followp(self):
|
||||
data = self
|
||||
company_id = data.company_id.id
|
||||
context = self.env.context
|
||||
self._cr.execute(
|
||||
'''SELECT
|
||||
l.partner_id,
|
||||
l.followup_line_id,
|
||||
l.date_maturity,
|
||||
l.date, l.id
|
||||
FROM account_move_line AS l
|
||||
LEFT JOIN account_account AS a
|
||||
ON (l.account_id=a.id)
|
||||
WHERE (l.full_reconcile_id IS NULL)
|
||||
AND a.account_type = 'asset_receivable'
|
||||
AND (l.partner_id is NOT NULL)
|
||||
AND (l.debit > 0)
|
||||
AND (l.company_id = %s)
|
||||
AND (l.blocked = False)
|
||||
ORDER BY l.date''' % (company_id))
|
||||
move_lines = self._cr.fetchall()
|
||||
old = None
|
||||
fups = {}
|
||||
fup_id = 'followup_id' in context and context[
|
||||
'followup_id'] or data.followup_id.id
|
||||
date = 'date' in context and context['date'] or data.date
|
||||
date = fields.Date.to_string(date)
|
||||
current_date = datetime.date(*time.strptime(date, '%Y-%m-%d')[:3])
|
||||
self._cr.execute(
|
||||
'''SELECT *
|
||||
FROM followup_line
|
||||
WHERE followup_id=%s
|
||||
ORDER BY delay''' % (fup_id,))
|
||||
|
||||
for result in self._cr.dictfetchall():
|
||||
delay = datetime.timedelta(days=result['delay'])
|
||||
fups[old] = (current_date - delay, result['id'])
|
||||
old = result['id']
|
||||
|
||||
partner_list = []
|
||||
to_update = {}
|
||||
|
||||
for partner_id, followup_line_id, date_maturity, date, id in \
|
||||
move_lines:
|
||||
if not partner_id:
|
||||
continue
|
||||
if followup_line_id not in fups:
|
||||
continue
|
||||
stat_line_id = partner_id * 10000 + company_id
|
||||
if date_maturity:
|
||||
date_maturity = fields.Date.to_string(date_maturity)
|
||||
if date_maturity <= fups[followup_line_id][0].strftime(
|
||||
'%Y-%m-%d'):
|
||||
if stat_line_id not in partner_list:
|
||||
partner_list.append(stat_line_id)
|
||||
to_update[str(id)] = {'level': fups[followup_line_id][1],
|
||||
'partner_id': stat_line_id}
|
||||
elif date and date <= fups[followup_line_id][0].strftime(
|
||||
'%Y-%m-%d'):
|
||||
if stat_line_id not in partner_list:
|
||||
partner_list.append(stat_line_id)
|
||||
to_update[str(id)] = {'level': fups[followup_line_id][1],
|
||||
'partner_id': stat_line_id}
|
||||
return {'partner_ids': partner_list, 'to_update': to_update}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="view_om_account_followup_print" model="ir.ui.view">
|
||||
<field name="name">account.followup.print.form</field>
|
||||
<field name="model">followup.print</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Send follow-ups">
|
||||
<group col="4">
|
||||
<field name="date" groups="base.group_no_one"/>
|
||||
<field name="followup_id"
|
||||
groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<p class="oe_grey">
|
||||
This action will send follow-up emails, print the
|
||||
letters and
|
||||
set the manual actions per customer, according to the
|
||||
follow-up levels defined.
|
||||
</p>
|
||||
<footer>
|
||||
<button name="do_process"
|
||||
string="Send emails and generate letters"
|
||||
type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link"
|
||||
special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_om_account_followup_print" model="ir.actions.act_window">
|
||||
<field name="name">Send Follow-Ups</field>
|
||||
<field name="res_model">followup.print</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_finance_followup" parent="account.menu_finance"
|
||||
name="Follow-Ups"
|
||||
groups="account.group_account_invoice"/>
|
||||
|
||||
<menuitem action="action_om_account_followup_print"
|
||||
id="om_account_followup_print_menu"
|
||||
parent="menu_finance_followup"
|
||||
name="Send Letters and Emails"
|
||||
groups="account.group_account_user,account.group_account_manager"
|
||||
sequence="2"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class FollowupSendingResults(models.TransientModel):
|
||||
_name = 'followup.sending.results'
|
||||
_description = 'Results from the sending of the different letters and emails'
|
||||
|
||||
def do_report(self):
|
||||
return self.env.context.get('report_data')
|
||||
|
||||
def do_done(self):
|
||||
return {}
|
||||
|
||||
def _get_description(self):
|
||||
return self.env.context.get('description')
|
||||
|
||||
def _get_need_printing(self):
|
||||
return self.env.context.get('needprinting')
|
||||
|
||||
description = fields.Text("Description", readonly=True,default=_get_description)
|
||||
needprinting = fields.Boolean("Needs Printing", default=_get_need_printing)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="view_om_account_followup_sending_results" model="ir.ui.view">
|
||||
<field name="name">followup.sending.results.form</field>
|
||||
<field name="model">followup.sending.results</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Summary of actions">
|
||||
<field name="description" widget="html"
|
||||
class="oe_view_only"/>
|
||||
<footer>
|
||||
<field name="needprinting" invisible="1"/>
|
||||
<div attrs="{'invisible':[('needprinting','=', False)]}">
|
||||
<button name="do_report" string="Download Letters"
|
||||
type="object" class="oe_highlight"/>
|
||||
</div>
|
||||
<div attrs="{'invisible':[('needprinting','!=', False)]}">
|
||||
<button name="do_done" string="Close" type="object"
|
||||
class="oe_highlight"/>
|
||||
</div>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
Loading…
Add table
Add a link
Reference in a new issue