from odoo import fields, models,api,_ from odoo.exceptions import UserError, ValidationError, Warning from datetime import datetime,date import os,secrets import decimal import base64 import logging import json _logger = logging.getLogger(__name__) code_journal='IN' date_compta=fields.datetime.now() total_debit=total_credit=0 no_mvt=1 class AccountingFileWizard(models.TransientModel): _name = 'accounting.file.wizard' _description = 'accounting file wizard' start_date=fields.Datetime('start date',required=True,default=lambda self: self._compute_start_date()) debug_mode=fields.Boolean('debug mode',default=True) export_donation_lines=fields.Boolean('export donation lines',default=True) export_membership_lines=fields.Boolean('export_membership_lines',default=True) export_event_lines=fields.Boolean('export_event_lines',default=True) export_booking_event_lines=fields.Boolean('export_booking_event_lines',default=True) export_out_refund_lines=fields.Boolean('export_out_refund_lines',default=True) export_end_of_stay_lines=fields.Boolean('export_end_of_stay_lines',default=True) def _compute_start_date(self): date_max=[] #recherche de la date d'export d'écriture la plus récente query="select max(date_compta) as date_compta from donation_donation" self._cr.execute(query) query_res = self._cr.dictfetchall() for r in query_res: d_date_compta=r['date_compta'] if d_date_compta: date_max.append(d_date_compta) query="select max(date_compta) as date_compta from kalachakra_membership" self._cr.execute(query) query_res = self._cr.dictfetchall() for r in query_res: m_date_compta=r['date_compta'] if m_date_compta: date_max.append(m_date_compta) query="select max(date_compta) as date_compta from event_registration" self._cr.execute(query) query_res = self._cr.dictfetchall() for r in query_res: e_date_compta=r['date_compta'] if e_date_compta: date_max.append(e_date_compta) if date_max: return max(date_max) else: return fields.Date.context_today(self) #accounting_date=fields.Date(string='Accounting date',required=True) def action_create_accounting_file(self): global total_debit global total_credit total_debit=0 total_credit=0 # donation=self.env['donation.donation'].search([]) # for d in donation: # d.date_compta=False # membership=self.env['kalachakra.membership'].search([]) # for m in membership: # m.date_compta=False # reg=self.env['event.registration'].search([]) # for r in reg: # r.date_compta=False # r.date_compta_down_payment=False # invoices=self.env['account.move'].search([]) # for i in invoices: # i.date_compta_out_refund=False # i.date_compta=False # return True tmstp=secrets.token_hex(16) filename='/tmp/accounting_file_'+tmstp+'.csv' f = open(filename, "a",encoding="cp1252") #N° mouvement 1-5 #Code du journal "IN" 6-7 #Date 8-17 (10 cars) ex:01/04/2022 #N° de compte 18-23 (6 cars) #Libellé 24- (12+ 13 cars) 12:Initial prénom+nom 13:lib evt exemple :E Meurinne Besoins cent #Débit ex: 200,00 #Crédit ex : 200,00 #N° de pièce: ref transaction , ex: txD-457 fic_line='"N° mouvement;Code du journal;Date;N° de compte;Libellé;Débit;Crédit;N° de pièce'+'"'+"\n" #fic_line=fic_line.encode(encoding="cp1252",errors='ignore') f.write(fic_line) if self.export_donation_lines:self.donation_lines(f) if self.export_membership_lines:self.membership_lines(f) if self.export_event_lines:self.event_lines(f) if self.export_booking_event_lines:self.booking_event_lines(f) if self.export_out_refund_lines:self.out_refund_lines(f) if self.export_end_of_stay_lines:self.end_of_stay_lines(f) fic_line="TOTAL_DEBIT="+str(total_debit)+ " TOTAL CREDIT="+str(total_credit) #fic_line=fic_line.encode(encoding="cp1252",errors='ignore') f.write(fic_line) f.close f = open(filename, "rb") data = f.read() #raise UserError('gg'+f.read()) vals={} vals['accounting_file']=base64.encodebytes(data) vals['document_fname']='export_comptable.csv' vals['exported_date']=fields.Date.context_today(self) vals['start_date']=self.start_date res=self.env['accounting.file'].create(vals) f.close os.unlink(filename) #display account deposit return { 'name': 'Account deposit form', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'accounting.file', 'res_id': int(res.id), 'type': 'ir.actions.act_window', 'target': 'current' } def _accounting_line(self,no_mvt,date_line,account_number,lib,debit,credit,lib_piece): str_line='"'+str(no_mvt)+';'+'IN'+';'+date_line+';'+account_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'"'+'\n' return str_line def donation_lines(self,f): global total_debit global total_credit global no_mvt #écritures pour les dons validés (donc payés), non déjà exportés donation=self.env['donation.donation'].search([('date_compta','=',False),('state','=','done')]) #raise UserError(donation) for d in donation: date_payment=d.donation_date #recherche de la date de paiement du don trans=self.env['payment.transaction'].search([('donation_ids','in',d.id),('state','=','done')],limit=1) if trans : date_payment=trans.date.date() #if datetime(d.donation_date.year, d.donation_date.month, d.donation_date.day)0 and reg.invoice_id.payment_state=='paid' and reg.date_compta==False : if reg.date_payment and reg.date_payment=self.start_date.date(): self.booking_down_payment_invoice_lines(f,reg) #si solde payée pas exporté : if reg.balance_invoice_id.payment_state=='paid' and not reg.date_compta: if reg.date_payment_balance and reg.date_payment_balance>=self.start_date.date(): self.booking_balance_invoice_lines(f,reg) _logger.error('TOTAL DEBIT '+str(total_debit)+' TOTAL CREDIT '+str(total_credit)) return True def booking_balance_invoice_lines(self,f,reg) : global total_debit global total_credit global no_mvt membership_amount=0 donation_amount=0 membership_credit_line=False donation_credit_line=False #if not reg.event_id.participation_product_id.property_account_income_id: raise UserError(_("no credit account found for product %r",reg.event_id.participation_product_id.name)) account_credit_number=self._file_format('170000',6) firstname=reg.partner_id.firstname name=reg.partner_id.name if not name : name='N/A' if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) lib2=self._file_format(reg.event_id.booking_product_id.name,13) lib=lib1+' '+lib2 if not self.debug_mode: reg.date_compta=date_compta down_payment=False balance_payment=True #if not reg.balance_invoice_id.payment_mode_id.fixed_journal_id: raise UserError(_("no account found payment mode %r",reg.balance_invoice_id.payment_mode_id.name)) #account_debit_number=self._file_format(str(reg.down_payment_invoice_id.payment_mode_id.fixed_journal_id.default_account_id.code),6) # trans=self.env['payment.transaction'].search([('invoice_ids','in',reg.down_payment_invoice_id.id),('state','=','done')],limit=1) # if trans and trans.acquirer_id.name=='Paypal': account_debit_number=self._file_format(str(self.env['account.payment.mode'].search([('name','=','Paypal')]).fixed_journal_id.default_account_id.code),6) # if trans and trans.acquirer_id.name=='Paiement par carte bancaire': account_debit_number=self._file_format(str(self.env['account.payment.mode'].search([('name','=','CB')]).fixed_journal_id.default_account_id.code),6) # if not trans: account_debit_number='' for p in reg.balance_invoice_id.payment_ids: account_debit_number=self._file_format(str(self.env['account.journal'].search([('id','=',int(p.journal_id))]).default_account_id.code),6) break date_line=self._payment_date(reg.balance_invoice_id) #recherche de l'adhésion membership_credit_line=False membership=self.env['kalachakra.membership'].search([('date_compta','=',False),('balance_invoice_id','=',int(reg.balance_invoice_id))]) if membership: membership_credit_line=True membership_amount=membership.amount #recherche de dons donation_credit_line=False donations=donation_booking=self.env['donation.donation'].search([('date_compta','=',False),('invoice_id','=',int(reg.balance_invoice_id))]) if donations: donation_credit_line=True for d in donations: donation_amount+=donations.amount_total trans=self.env['payment.transaction'].search([('state','=','done'),('invoice_ids','in',reg.balance_invoice_id.id)],limit=1) if trans: lib_piece=self._file_format(trans.reference,20) else: lib_piece=self._file_format(reg.balance_invoice_id.name,20) amount=reg.balance_invoice_id.amount_total if amount==0: return False credit='' debit=str(amount) account_number=account_debit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_debit+=amount if not amount: amount=0 amount=reg.balance_invoice_id.amount_total-membership_amount-donation_amount debit='' credit=str(amount) account_number=account_credit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_credit+=amount if membership_credit_line: debit='' credit=str(membership_amount) account_number=self._file_format('756100',6) fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_credit+=membership_amount if donation_credit_line: for d in donations : debit='' amount=d.amount_total credit=str(amount) account_number=account_credit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_credit+=amount def booking_down_payment_invoice_lines(self,f,reg): global total_debit global total_credit global no_mvt membership_amount=0 donation_amount=0 membership_credit_line=False donation_credit_line=False #if not reg.event_id.participation_product_id.property_account_income_id: raise UserError(_("no credit account found for product %r",reg.event_id.participation_product_id.name)) account_credit_number=self._file_format('170000',6) firstname=reg.partner_id.firstname name=reg.partner_id.name if not name : name='N/A' if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) lib2=self._file_format(reg.event_id.booking_product_id.name,13) lib=lib1+' '+lib2 if not self.debug_mode: reg.date_compta_down_payment=date_compta down_payment=True balance_payment=False donation_credit_line=False membership_credit_line=False #if not reg.down_payment_invoice_id.payment_mode_id.fixed_journal_id: raise UserError(_("no account found payment mode %r",reg.down_payment_invoice_id.payment_mode_id.name)) account_debit_number=self._file_format(str(reg.down_payment_invoice_id.payment_mode_id.fixed_journal_id.default_account_id.code),6) trans=self.env['payment.transaction'].search([('invoice_ids','in',reg.down_payment_invoice_id.id),('state','=','done')],limit=1) if trans and trans.acquirer_id.name=='Paypal': account_debit_number=self._file_format(str(self.env['account.payment.mode'].search([('name','=','Paypal')]).fixed_journal_id.default_account_id.code),6) if trans and trans.acquirer_id.name=='Paiement par carte bancaire': account_debit_number=self._file_format(str(self.env['account.payment.mode'].search([('name','=','CB')]).fixed_journal_id.default_account_id.code),6) amount=reg.down_payment_invoice_id.amount_total date_line=self._date_format(reg.date_payment_down_payment) trans=self.env['payment.transaction'].search([('state','=','done'),('invoice_ids','in',reg.down_payment_invoice_id.id)],limit=1) if trans: lib_piece=self._file_format(trans.reference,20) else: lib_piece=self._file_format(reg.down_payment_invoice_id.name,20) amount=reg.down_payment_invoice_id.amount_total if amount==0: return False credit='' debit=str(amount) account_number=account_debit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_debit+=amount #credit(s) line(s) #participation credit line if not amount: amount=0 amount=reg.down_payment_invoice_id.amount_total debit='' credit=str(amount) account_number=account_credit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_credit+=amount def booking_invoice_lines(self,f,reg): global total_debit global total_credit global no_mvt #_logger.error('acompte:'+str(reg.down_payment_invoice_id.payment_state)+' solde :'+str(reg.balance_invoice_id.payment_state)+' date_compta'+str(reg.date_compta)+' date_compta_down_payment:'+str(reg.date_compta_down_payment)) membership_amount=0 donation_amount=0 membership_credit_line=False donation_credit_line=False #if not reg.event_id.participation_product_id.property_account_income_id: raise UserError(_("no credit account found for product %r",reg.event_id.participation_product_id.name)) account_credit_number=self._file_format('170000',6) firstname=reg.partner_id.firstname name=reg.partner_id.name if not name : name='N/A' if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) lib2=self._file_format(reg.event_id.booking_product_id.name,13) lib=lib1+' '+lib2 if not self.debug_mode: reg.date_compta=date_compta case_line=1 down_payment=False balance_payment=False #if not reg.invoice_id.payment_mode_id.fixed_journal_id: raise UserError(_("no account found payment mode %r",reg.invoice_id.payment_mode_id.name)) account_debit_number=self._file_format(str(reg.invoice_id.payment_mode_id.fixed_journal_id.default_account_id.code),6) trans=self.env['payment.transaction'].search([('invoice_ids','in',reg.invoice_id.id),('state','=','done')],limit=1) if trans and trans.acquirer_id.name=='Paypal': account_debit_number=self._file_format(str(self.env['account.payment.mode'].search([('name','=','Paypal')]).fixed_journal_id.default_account_id.code),6) if trans and trans.acquirer_id.name=='Paiement par carte bancaire': account_debit_number=self._file_format(str(self.env['account.payment.mode'].search([('name','=','CB')]).fixed_journal_id.default_account_id.code),6) #recherche de l'adhésion membership_credit_line=False membership=self.env['kalachakra.membership'].search([('invoice_id','=',int(reg.invoice_id))]) if membership: membership_credit_line=True membership_amount=membership.amount #recherche de dons donation_credit_line=False donations=donation_booking=self.env['donation.donation'].search([('invoice_id','=',int(reg.invoice_id))]) if donations: donation_credit_line=True for d in donations: donation_amount+=d.amount_total date_line=self._date_format(reg.date_payment) trans=self.env['payment.transaction'].search([('state','=','done'),('invoice_ids','in',reg.invoice_id.id)],limit=1) if trans: lib_piece=self._file_format(trans.reference,20) else: lib_piece=self._file_format(reg.invoice_id.name,20) #debit line amount=reg.invoice_id.amount_total if amount==0: return False credit='' debit=str(amount) account_number=account_debit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_debit+=amount #credit(s) line(s) #participation credit line if not amount: amount=0 amount=amount-membership_amount-donation_amount debit='' credit=str(amount) account_number=account_credit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_credit+=amount if membership_credit_line: debit='' credit=str(membership_amount) account_number=self._file_format('756100',6) fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_credit+=membership_amount if donation_credit_line: for d in donations : debit='' amount=d.amount_total credit=str(amount) account_number=account_credit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt=no_mvt+1 total_credit+=amount def out_refund_lines(self,f): global total_debit global total_credit global no_mvt #écritures pour les avoirs pas encore utilisés ou payés mais jamais passé en compta out_refund_invoices=self.env['account.move'].search([('move_type','=','out_refund'),('state','=','posted'),('payment_state','=','not_paid'),('date_compta','=',False),('date_compta_out_refund','=',False)]) for invoice in out_refund_invoices: if not self.debug_mode: invoice.date_compta_out_refund=date_compta firstname=invoice.partner_id.firstname name=invoice.partner_id.name if not name : name='N/A' if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) lines=self.env['account.move.line'].search([('move_id','=',int(invoice.id))],limit=1) if lines: lib2=self._file_format(lines.name,13) else: lib2='' lib=lib1+' '+lib2 lib_piece=self._file_format(invoice.name,20) #écriture de débit amount=invoice.amount_total account_debit_number='170000' date_line=self._date_format(invoice.invoice_date) if amount==0: continue debit=str(amount) credit='' account_number=account_debit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt+=1 total_debit+=amount #écriture de crédit debit='' credit=str(amount) account_credit_number='170000' account_number=account_credit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt+=1 total_credit+=amount #écritures pour les avoirs qui ont été utilisés #écriture Débit 411000 – Crédit 170000 out_refund_invoices=self.env['account.move'].search([('move_type','=','out_refund'),('payment_state','=','paid'),('date_compta','=',False)]) for invoice in out_refund_invoices: #_logger.error(invoice.id) if not self.debug_mode: invoice.date_compta=date_compta firstname=invoice.partner_id.firstname name=invoice.partner_id.name #_logger.error(name) if not name : name='N/A' if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) lib2='' reg=self.env['event.registration'].search(['|',('invoice_id','=',int(invoice.out_invoice_id)),('balance_invoice_id','=',int(invoice.out_invoice_id))]) if reg: lib2=self._file_format(reg.event_id.name,13) else: lib2=self._file_format(invoice.payment_reference,13) lib=lib1+' '+lib2 if reg: lib_piece=self._file_format(invoice.out_invoice_id.name,20) else : lib_piece=self._file_format(invoice.name,20) #écriture de débit amount=invoice.amount_total account_debit_number='170000' #date du paiement #_logger.error(self._payment_date_ok(invoice.out_invoice_id)) if not self._payment_date_ok(invoice):continue date_line=self._payment_date(invoice) if amount==0: continue debit=str(amount) credit='' account_number=account_debit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt+=1 total_debit+=amount #écriture de crédit debit='' credit=str(amount) if invoice.out_invoice_id: account_credit_number='170000' else: account_credit_number= self._payment_account_number(invoice) account_number=account_credit_number fic_line=self._accounting_line(no_mvt,date_line,account_number,lib,debit,credit,lib_piece) f.write(fic_line) no_mvt+=1 total_credit+=amount def _file_format(self,data,nbcars): if data: if len(data)>nbcars: return data[0:nbcars] else: return data else: return '' def _payment_(self,move_id): if move_id.invoice_payments_widget: payment_info=json.loads(move_id.invoice_payments_widget) if payment_info: if datetime.strptime(payment_info['content'][0]['date'],'%Y-%m-%d')>self.start_date: return False else: return True else:return True def _payment_date_ok(self,move): if move.invoice_payments_widget: payment_info=json.loads(move.invoice_payments_widget) if payment_info: #_logger.error(payment_info['content'][0]['date']) if datetime.strptime(payment_info['content'][0]['date'],'%Y-%m-%d')>=self.start_date: return True else: return False else: return False def _payment_date(self,move_id): if move_id.invoice_payments_widget: payment_info=json.loads(move_id.invoice_payments_widget) if payment_info: return self._date_format(payment_info['content'][0]['date']) # else: return 'False' else:return 'False' def _payment_account_number(self,move_id): if move_id.invoice_payments_widget: payment_info=json.loads(move_id.invoice_payments_widget) if payment_info: account_payment_id=payment_info['content'][0]['account_payment_id'] #payment_mode_id.fixed_journal_id.default_account_id.code account_number=self.env['account.payment'].search([('id','=',int(account_payment_id))]).journal_id.default_account_id.code return account_number else: return '' else:return '' def _date_format(self,data): #_logger.error('date='+str(data)) if data: r=str(data).split('-') if len(r[2])==1:r[2]='0'+r[2] if len(r[1])==1:r[1]='0'+r[1] return r[2]+'/'+r[1]+'/'+r[0] else: return 'False'