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 class AccountingFileWizard(models.TransientModel): _name = 'accounting.file.wizard' _description = 'accounting file wizard' #accounting_date=fields.Date(string='Accounting date',required=True) def action_create_accounting_file(self): #debug 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 tmstp=secrets.token_hex(16) filename='/tmp/accounting_file_'+tmstp+'.txt' f = open(filename, "a") date_compta=fields.datetime.now() #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 no_mvt=1 code_journal='IN' fic_line="N° mouvement;Code du journal;Date;N° de compte;Libellé;Débit;Crédit;N° de pièce"+"\n" f.write(fic_line) #é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')]) for d in donation: #on ne prend pas en compte les dons liés à une retraite #car traité avec les retraites if d.invoice_id: continue d.date_compta=date_compta #if not d.payment_mode_id: raise UserError(_("no payment mode found for donation %r ",donation.number)) #if not d.payment_mode_id.fixed_journal_id: raise UserError(_("no account found for payment mode %r",d.payment_mode_id.name)) account_debit_number=self._file_format(str(d.payment_mode_id.fixed_journal_id.default_account_id.code),6) firstname=d.partner_id.firstname name=d.partner_id.name if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) #lib1=lib1[11] date_line=self._date_format(str(d.donation_date)) #recherche de la transaction lib_piece=self._file_format(d.number,20) pt=self.env['payment.transaction'].search([('donation_ids','in',d.id)]) if pt: lib_piece=pt.reference for line in d.line_ids: affectation=line.product_id.name amount=str(line.amount) #if not line.product_id.property_account_income_id: raise UserError(_("no credit account found for product %r",line.product_id.name)) account_credit_number=self._file_format(line.product_id.property_account_income_id.code,6) break #credit line lib2=self._file_format(affectation,13) lib=lib1+' '+lib2 debit='' credit=str(amount) fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_credit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 #debit line debit=str(amount) credit='' fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_debit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 #écritures pour les ADHESIONS réglées non déjà exportés membership=self.env['kalachakra.membership'].search([('date_compta','=',False),('state','=','done')]) for m in membership: m.date_compta=date_compta #on ne prend pas en compte les adhésions liés à une retraite #car traité avec les retraites if m.invoice_id: continue #si l'adhésion est liée à une facture, alors on récupère la facture pour trouver le mode de paiement if m.invoice_id: #if not m.invoice_id.payment_id.fixed_journal_id: raise UserError(_("no account found for payment mode %r",m.invoice_id.payment_id.name)) account_debit_number=self._file_format(str(m.invoice_id.payment_id.fixed_journal_id.default_account_id.code),6) #si l'adhésion est liée à une transaction,le mode de paiement est CB elif m.transaction_id: CB_pm=self.env['account.payment.mode'].search([('name','=','CB')],limit=1) if CB_pm: account_debit_number=self._file_format(str(CB_pm.fixed_journal_id.default_account_id.code),6) else: raise UserError(_('please configure CB payement mode')) #sinon on prend le mode de paiement au niveau de la fiche d'adhésion else: if m.payment_mode_id: #if not m.payment_mode_id: raise UserError(_("no payment mode found for membership %r",m.partner_id.name)) account_debit_number=self._file_format(str(m.payment_mode_id.fixed_journal_id.default_account_id.code),6) firstname=m.partner_id.firstname name=m.partner_id.name if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) date_line=self._date_format(str(m.start_date)) amount=str(m.amount) #if not m.product_id.property_account_income_id: raise UserError(_("no credit account found for product %r",m.product_id.name)) account_credit_number=self._file_format(m.product_id.property_account_income_id.code,6) affectation=m.product_id.name #lib pièce if m.transaction_id: lib_piece=self._file_format(m.transaction_id.reference,20) elif m.invoice_id: lib_piece=self._file_format(m.invoice_id.name,20) else: lib_piece=self._file_format(m.partner_id.name,20) #credit line lib2=self._file_format(affectation,13) lib=lib1+' '+lib2 debit='' credit=str(amount) fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_credit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 #debit line debit=str(amount) credit='' fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_debit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 #écritures pour les inscriptions évts hors RETRAITES avec facture payée non déjà exportés registration=self.env['event.registration'].search([('date_compta','=',False),('payment_status','=','paid'),('event_id.booking_event','=',False),('event_id.individual_booking_event','=',False)]) if registration: for reg in registration: reg.date_compta=date_compta #if not reg.invoice_id.payment_mode_id.fixed_journal_id: raise UserError(_("no account found for payment mode %r",reg.invoice_id.payment_mode_id)) account_debit_number=self._file_format(str(reg.invoice_id.payment_mode_id.fixed_journal_id.default_account_id.code),6) firstname=m.partner_id.firstname name=m.partner_id.name if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) #date du paiement date_line=str(m.write_date.year)+'-'+str(m.write_date.month)+'-'+str(m.write_date.day) date_line=self._date_format(date_line) amount=str(m.amount) #if not reg.event_id.participation_product_id: raise UserError(_("no credit account found for product %r",reg.event_id.participation_product_id.name)) account_credit_number=self._file_format(reg.event_id.participation_product_id.property_account_income_id.code,6) affectation=reg.event_id.participation_product_id.name #si facture liée à une transaction: trans=self.env['payment.transaction'].search([('invoice_ids','in',reg.invoice_id.id),('state','=','done')]) if trans: lib_piece=self._file_format(trans.reference,20) else: lib_piece=self._file_format(reg.invoice_id.name,20) #credit line lib2=self._file_format(affectation,13) lib=lib1+' '+lib2 debit='' credit=str(amount) fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_credit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 #debit line debit=str(amount) credit='' fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_debit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 #écritures pour les inscription aux RETRAITES avec facture acomptes payés + factures soldes payés non déjà exporté registration=self.env['event.registration'].search(['|',('date_compta','=',False),('date_compta_down_payment','!=',False)]) for reg in registration: if reg: membership_amount=0 donation_amount=0 membership_credit_line=False donation_credit_line=False reg.date_compta=date_compta #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(reg.event_id.participation_product_id.property_account_income_id.code,6) firstname=reg.firstname name=reg.name if not firstname: firstname=' ' lib1=firstname[0]+' '+name lib1=self._file_format(lib1,12) lib2=self._file_format(reg.event_id.participation_product_id.name,13) lib=lib1+' '+lib2 #si pas de facture d'acompte et facture payée: if not reg.down_payment_invoice_id and reg.payment_status=='paid' and not reg.date_compta : 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) amount=reg.invoice_id.amount_total #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 #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 date_line=self._date_format(str(reg.invoice_id.write_date)) trans=self.env['payment.transaction'].search([('invoice_ids','in',reg.invoice_id)]) #si facture d'acompte payée et solde payée et pas encore exportée : if reg.payment_status=='paid' and not reg.date_compta: reg.date_compta=date_compta down_payment=True balance_payment=True membership_amount=0 donation_amount=0 membership_credit_line=False donation_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) amount=reg.down_payment_invoice_id.amount_total+reg.balance_invoice_id.amount_total date_line=self._date_format(str(reg.balance_invoice_id.write_date)) #recherche de l'adhésion membership=self.env['kalachakra.membership'].search([('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([('invoice_id','=',int(reg.balance_invoice_id))]) if donations: donation_credit_line=True for d in donations: donation_amount=donation_amount+d.amount_total trans=self.env['payment.transaction'].search([('invoice_ids','in',reg.invoice_id)]) #si facture d'acompte payée pas encore exporté et solde non payée : if reg.payment_status=='down payment paid' and not reg.date_compta_down_payment: 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) amount=reg.down_payment_invoice_id.amount_total date_line=self._date_format(str(reg.down_payment_invoice_id.write_date)) #si facture d'acompte payée et exporté et solde payée pas exporté : if reg.payment_status=='paid' and reg.date_compta_down_payment: 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) date_line=self._date_format(str(reg.balance_invoice_id.write_date)) #recherche de l'adhésion membership_credit_line=False membership=self.env['kalachakra.membership'].search([('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([('invoice_id','=',int(reg.balance_invoice_id))]) if donations: donation_credit_line=True for d in donations: amount_donation=amount_donation+donations.amount_total #écritures pour les inscription aux RETRAITES avec facture complémentaire if trans: lib_piece=self._file_format(trans.reference,20) else: lib_piece=self._file_format(lib2,20) #debit line debit=str(amount) credit='' fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_debit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 #credit(s) line(s) #participation credit line if not amount: amount=0 amount=float(amount)-float(membership_amount)-float(donation_amount) debit='' credit=str(amount) fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_credit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 if membership_credit_line: debit='' credit=str(membership_amount) fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_credit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 if donation_credit_line: for d in donations : debit='' credit=str(d.amount_total) fic_line=str(no_mvt)+';'+'IN'+';'+date_line+';'+account_credit_number+';'+lib+';'+debit+';'+credit+';'+lib_piece+'\n' f.write(fic_line) no_mvt=no_mvt+1 f.close f = open(filename, "r") data = str.encode(f.read(), 'utf-8') #raise UserError('gg'+f.read()) vals={} vals['accounting_file']=base64.encodebytes(data) vals['document_fname']='export_comptable.txt' vals['exported_date']=fields.Date.context_today(self) 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' } #rajouter en fin de fichier un total DEBIT et un total CREDIT f.close #création de l'export en base vals={} f = open(filename, "r") data = str.encode(f.read(), 'utf-8') vals['accounting_file']=base64.encodebytes(data) vals['document_fname']='export_comptable.csv' vals['exported_date']=fields.Date.context_today(self) res=self.env['accounting.file'].create(vals) f.close os.unlink(filename) #affichage de l'export return { 'name': 'Account file form', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'accounting.file', 'res_id': int(res.id), 'type': 'ir.actions.act_window', 'target': 'current' } return True def _file_format(self,data,nbcars): if data: if len(data)>nbcars: return data[0:nbcars] else: return data else: return '' def _date_format(self,data): r=data.split('-') return r[2]+'/'+r[1]+'/'+r[0]