1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 ##############################################################################
29 from osv import fields, osv
30 from tools.translate import _
32 _email_summary_form = """<?xml version="1.0"?>
33 <form string="Summary">
34 <field name="summary" height="300" width="800"/>
37 _email_summary_fields = {
38 'summary': {'string': 'Summary', 'type': 'text', 'required': False, 'readonly': True},
41 _followup_wizard_screen1_form = """<?xml version="1.0"?>
42 <form string="Follow-up and Date Selection">
43 <field name="followup_id"/>
47 _followup_wizard_screen1_fields = {
48 'date': {'string': 'Follow-up Sending Date', 'type': 'date', 'required': True, 'help':"This field allow you to select a forecast date to plan your follow-ups"},
49 'followup_id': {'string': 'Follow-up', 'type':'many2one', 'relation':'account_followup.followup', 'required': True,},
54 _followup_wizard_all_form = """<?xml version="1.0"?>
55 <form string="Select partners" colspan="4">
57 <page string="Partner Selection">
58 <separator string="Select partners to remind" colspan="4"/>
59 <field name="partner_ids" colspan="4" nolabel="1"/>
61 <page string="Email Settings">
62 <field name="email_conf" colspan="4"/>
63 <field name="partner_lang" colspan="4"/>
64 <field name="email_subject" colspan="4"/>
65 <separator string="Email body" colspan="4" attrs="{'readonly':[('partner_lang','=',True)]}"/>
66 <field name="email_body" colspan="4" nolabel="1"/>
67 <separator string="Legend" colspan="4"/>
69 <label string="%(partner_name)s: Partner name" colspan="2"/>
70 <label string="%(user_signature)s: User name" colspan="2"/>
71 <label string="%(followup_amount)s: Total Amount Due" colspan="2"/>
72 <label string="%(date)s: Current Date" colspan="2"/>
73 <label string="%(company_name)s: User's Company name" colspan="2"/>
74 <label string="%(company_currency)s: User's Company Currency" colspan="2"/>
75 <label string="%(heading)s: Move line header" colspan="2"/>
76 <label string="%(line)s: Account Move lines" colspan="2"/>
81 _followup_wizard_all_fields = {
86 'relation': 'account_followup.stat',
89 'string': "Send email confirmation",
93 'string' : "Email Subject",
96 'default': 'Invoices Reminder'
99 'string': "Send Email in Partner Language",
102 'help':'Do not change message text, if you want to send email in partner language, or configre from company'
105 'string': "Email body",
110 Dear %(partner_name)s,
112 Please find in attachment a reminder of all your unpaid invoices, for a total amount due of:
114 %(followup_amount).2f %(company_currency)s
125 class followup_all_print(wizard.interface):
126 def _update_partners(self, cr, uid, data, context):
127 to_update = data['form']['to_update']
128 for id in to_update.keys():
129 if to_update[id]['partner_id'] in data['form']['partner_ids'][0][2]:
131 "UPDATE account_move_line "\
132 "SET followup_line_id=%s, followup_date=%s "\
134 (to_update[id]['level'],
135 data['form']['date'], int(id),))
138 def _sendmail(self ,cr, uid, data, context):
139 if data['form']['email_conf']:
144 pool = pooler.get_pool(cr.dbname)
145 data_user = pool.get('res.users').browse(cr,uid,uid)
146 line_obj = pool.get('account_followup.stat')
147 move_lines = line_obj.browse(cr,uid,data['form']['partner_ids'][0][2])
150 for line in move_lines:
151 partners.append(line.name)
152 dict_lines[line.name.id] =line
153 for partner in partners:
154 ids_lines = pool.get('account.move.line').search(cr,uid,[('partner_id','=',partner.id),('reconcile_id','=',False),('account_id.type','in',['receivable'])])
155 data_lines = pool.get('account.move.line').browse(cr,uid,ids_lines)
156 followup_data = dict_lines[partner.id]
159 for adr in partner.address:
160 if adr.type=='contact':
163 if (not dest) and adr.type=='default':
166 src = tools.config.options['email_from']
167 if not data['form']['partner_lang']:
168 body = data['form']['email_body']
171 cxt['lang'] = partner.lang
172 body = pool.get('res.users').browse(cr, uid, uid, context=cxt).company_id.follow_up_msg
174 total_amt = followup_data.debit - followup_data.credit
178 subtotal_maturity = 0.0
180 l = '--------------------------------------------------------------------------------------------------------------------------'
181 head = l+ '\n' + 'Date'.rjust(10) + '\t' + 'Description'.rjust(10) + '\t' + 'Ref'.rjust(10) + '\t' + 'Maturity date'.rjust(10) + '\t' + 'Due'.rjust(10) + '\t' + 'Paid'.rjust(10) + '\t' + 'Maturity'.rjust(10) + '\t' + 'Litigation'.rjust(10) + '\n' + l
184 if i.date_maturity < time.strftime('%Y-%m-%d') and (i.debit - i.credit):
185 maturity = i.debit - i.credit
186 subtotal_due = subtotal_due + i.debit
187 subtotal_paid = subtotal_paid + i.credit
188 subtotal_maturity = subtotal_maturity + int(maturity)
189 balance = balance + (i.debit - i.credit)
190 move_line = move_line + (i.date).rjust(10) + '\t'+ (i.name).rjust(10) + '\t'+ (i.ref or '').rjust(10) + '\t' + (i.date_maturity or '').rjust(10) + '\t' + str(i.debit).rjust(10) + '\t' + str(i.credit).rjust(10) + '\t' + str(maturity).rjust(10) + '\t' + str(i.blocked).rjust(10) + '\n'
191 move_line = move_line + l + '\n'+ '\t\t\t' + 'Sub total'.rjust(35) + '\t' + (str(subtotal_due) or '').rjust(10) + '\t' + (str(subtotal_paid) or '').rjust(10) + '\t' + (str(subtotal_maturity) or '').rjust(10)+ '\n'
192 move_line = move_line + '\t\t\t' + 'Balance'.rjust(33) + '\t' + str(balance).rjust(10) + '\n' + l
194 'partner_name':partner.name,
195 'followup_amount':total_amt,
196 'user_signature':data_user.name,
197 'company_name':data_user.company_id.name,
198 'company_currency':data_user.company_id.currency_id.name,
201 'date':time.strftime('%Y-%m-%d'),
204 sub = tools.ustr(data['form']['email_subject'])
207 tools.email_send(src,dest,sub,body)
208 msg_sent += partner.name + '\n'
210 msg += partner.name + '\n'
213 summary = _("All E-mails have been successfully sent to Partners:.\n\n") + msg_sent
215 msg_unsent = _("E-Mail not sent to following Partners, Email not available !\n\n") + msg_unsent
216 msg_sent = msg_sent and _("\n\nE-Mail sent to following Partners successfully. !\n\n") + msg_sent
217 line = '=========================================================================='
218 summary = msg_unsent + line + msg_sent
219 return {'summary' : summary}
221 return {'summary' : '\n\n\nE-Mail has not been sent to any partner. If you want to send it, please tick send email confirmation on wizard.'}
223 def _get_partners(self, cr, uid, data, context):
224 pool = pooler.get_pool(cr.dbname)
226 "SELECT l.partner_id, l.followup_line_id,l.date_maturity, l.date, l.id "\
227 "FROM account_move_line AS l "\
228 "LEFT JOIN account_account AS a "\
229 "ON (l.account_id=a.id) "\
230 "WHERE (l.reconcile_id IS NULL) "\
231 "AND (a.type='receivable') "\
232 "AND (l.state<>'draft') "\
233 "AND (l.partner_id is NOT NULL) "\
236 move_lines = cr.fetchall()
239 fup_id = data['form']['followup_id']
241 current_date = datetime.date(*time.strptime(data['form']['date'],
245 "FROM account_followup_followup_line "\
246 "WHERE followup_id=%s "\
247 "ORDER BY sequence", (fup_id,))
248 for result in cr.dictfetchall():
249 delay = datetime.timedelta(days=result['delay'])
250 fups[old] = (current_date - delay, result['id'])
251 if result['start'] == 'end_of_month':
252 fups[old][0].replace(day=1)
255 fups[old] = (datetime.date(datetime.MAXYEAR, 12, 31), old)
259 for partner_id, followup_line_id, date_maturity,date, id in move_lines:
262 if followup_line_id not in fups:
265 if date_maturity <= fups[followup_line_id][0].strftime('%Y-%m-%d'):
266 if partner_id not in partner_list:
267 partner_list.append(partner_id)
268 to_update[str(id)]= {'level': fups[followup_line_id][1], 'partner_id': partner_id}
269 elif date and date <= fups[followup_line_id][0].strftime('%Y-%m-%d'):
270 if partner_id not in partner_list:
271 partner_list.append(partner_id)
272 to_update[str(id)]= {'level': fups[followup_line_id][1], 'partner_id': partner_id}
274 message = pool.get('res.users').browse(cr, uid, uid, context=context).company_id.follow_up_msg
276 return {'partner_ids': partner_list, 'to_update': to_update, 'email_body':message}
278 def _get_screen1_values(self, cr, uid, data, context):
279 pool = pooler.get_pool(cr.dbname)
280 company_id = pool.get('res.users').browse(cr, uid, uid).company_id.id
281 tmp = pool.get('account_followup.followup').search(cr, uid, [('company_id', '=', company_id)])
282 followup = tmp and tmp[0] or False
283 return {'date': time.strftime('%Y-%m-%d'), 'followup_id': followup}
287 'actions': [_get_screen1_values],
288 'result': {'type': 'form',
289 'arch': _followup_wizard_screen1_form,
290 'fields': _followup_wizard_screen1_fields,
293 ('next', 'Continue'),
298 'actions': [_get_partners],
299 'result': {'type': 'form',
300 'arch': _followup_wizard_all_form,
301 'fields': _followup_wizard_all_fields,
304 ('print','Print Follow Ups & Send Mails'),
309 'actions': [_update_partners],
310 'result': {'type': 'print',
311 'report':'account_followup.followup.print',
315 'actions': [_sendmail],
316 'result': {'type': 'form',
317 'arch': _email_summary_form,
318 'fields': _email_summary_fields,
319 'state':[('end','Ok')]
324 followup_all_print('account_followup.followup.print.all')
327 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: