endi.models.services package¶
Submodules¶
endi.models.services.bpf module¶
- class endi.models.services.bpf.BPFService¶
Bases :
objectHandle BPF initialization according to current law
- CERFA_VERSIONS = {'10443*14': <class 'endi.models.services.bpf.Cerfa_10443_14'>, '10443*15': <class 'endi.models.services.bpf.Cerfa_10443_15'>, '10443*16': <class 'endi.models.services.bpf.Cerfa_10443_16'>}¶
- classmethod check_businesses_bpf(query, financial_year)¶
- classmethod gen_bpf(business, financial_year)¶
- classmethod get(business_id, financial_year)¶
- classmethod get_or_create(business_id, financial_year)¶
- classmethod get_spec_from_year(year)¶
- classmethod get_spec_name_from_year(year)¶
- class endi.models.services.bpf.BPFSpecInterface¶
Bases :
object- classmethod stream_csv_rows(query)¶
- Paramètres:
Query<BPFData> (query) –
- class endi.models.services.bpf.BusinesssBPFDataMigrator_15to16¶
Bases :
objectTranform Cerfa 10443*15 data into 10443*15 data
Tries to tranform a BusinessBPFData from 2020 that was (wrongly) filled using a 10443*15 form into 10443*16 form data. Does its best, but errors could remain.
- INCOME_SOURCES_MAPPING = {0: 0, 1: 2, 2: 4, 3: 5, 4: 6, 5: 8, 6: 7, 7: 10, 8: 20, 9: 21, 10: 22, 11: 23, 12: 24, 13: 30, 14: 31, 15: 32, 16: 32}¶
- TRAINEE_TYPE_MAPPING = {0: 0, 1: 2, 2: 2, 3: 3, 4: 4}¶
- TRAINING_GOALS_MAPPING = {0: 0, 1: 1, 2: 2, 3: 3, 4: 10, 5: 11, 6: 12, 7: 13, 8: 14}¶
- classmethod migrate(bpf_data: BusinessBPFData) None¶
Mutate the bpf_data, trying to map data (wrongly) filled in a 10443*15 into 10443*16 form.
- class endi.models.services.bpf.Cerfa_10443_14¶
Bases :
BPFSpecInterfacehttps://www.formulaires.modernisation.gouv.fr/gf/getNotice.do?cerfaFormulaire=10443&cerfaNotice=50199 https://www.formulaires.modernisation.gouv.fr/gf/cerfa_10443.do
- INCOME_SOURCES = [(0, 'Entreprises pour la formation de leurs salariés', []), (None, 'Organismes paritaires collecteurs ou gestionnaires des fonds de la formation', [(1, 'contrats de professionnalisation'), (2, 'congés individuels de formation'), (3, 'compte personnel de formation'), (4, 'autres dispositifs (plan de formation, périodes de professionnalisation, …)'), (5, 'pour des formations dispensées dans le cadre d’autres dispositifs (plan de formation, périodes de professionnalisation')]), (6, "Fonds d'assurance", []), (7, 'Pouvoirs publics pour la formation de leurs agents (Etat, collectivités territoriales, établissements publics à caractère administratif)', []), (None, 'Pouvoirs publics pour la formation de publics spécifiques', [(8, 'Instances européennes'), (9, 'État'), (10, 'Conseils régionaux'), (11, 'Pôle emploi'), (12, 'Autres ressources publiques')]), (13, 'Contrats conclus avec des personnes à titre individuel et à leurs frais', []), (14, 'Contrats conclus avec d’autres organismes de formation', []), (15, 'Produits résultant de la vente d’outils pédagogiques', []), (16, 'Autres produits au titre de la formation professionnelle continue', [])]¶
- TRAINEE_TYPES = [(0, 'Salariés bénéficiant d’un financement par l’employeur, par un OPCA ou un OPACIF', []), (1, 'Personnes en recherche d’emploi bénéficiant d’un financement public', []), (2, 'Personnes en recherche d’emploi bénéficiant d’un financement OPCA', []), (3, 'Particuliers à leurs propres frais', []), (4, 'Autres stagiaires', [])]¶
- TRAINING_GOALS = [(None, 'Formations visant un diplôme ou un titre à finalité professionnelle (hors certificat de qualification professionnelle) inscrit au Répertoire national des certifications professionnelles (RNCP)', [(0, 'Niveau I et II (licence, maîtrise, master, DEA, DESS, diplôme d’ingénieur)'), (1, 'Niveau III (BTS, DUT, écoles de formation sanitaire et sociale…)'), (2, 'Niveau III (BTS, DUT, écoles de formation sanitaire et sociale…)'), (3, 'Niveau IV (BAC professionnel, BT, BP, BM…)')]), (4, 'Certificat de qualification professionnelle (CQP)', []), (5, 'Certification et/ou une habilitation inscrite à l’inventaire de la CNCP', []), (6, 'Autres formations professionnelles continues', []), (7, 'Bilan de compétences', []), (8, "Actions d'accompagnement à la validation des acquis d'expérience", [])]¶
- classmethod build_data_dict(bpf_data_query)¶
- classmethod build_template_context(bpf_data_query)¶
- classmethod cost_stats(bpf_data_query)¶
Data for « D. BILAN FINANCIER HORS TAXES »
- Returns dict:
of floats (keys: total, subcontracted, internal)
- classmethod get_income_sources_ids()¶
- classmethod get_trainee_types_ids()¶
- classmethod get_training_goals_ids()¶
- classmethod has_subcontract_stats(bpf_data_query)¶
Data for « F - 2. ACTIVITÉ EN PROPRE DE L’ORGANISME »
Gather data for everything that is not subcontract
- Renvoie:
info as row attributes : total_hours and headcount
- Rtype sqlalchemy.engine.RowProxy:
- classmethod income_stats(bpf_data_query)¶
Data for « C. BILAN FINANCIER HORS TAXES »
- Returns sqlalchemy.orm.Query:
- classmethod is_not_subcontract_stats(bpf_data_query)¶
Data for « F - 2. ACTIVITÉ EN PROPRE DE L’ORGANISME »
Gather data for everything that is not subcontract
- Renvoie:
info as row attributes : total_hours and headcount
- Rtype sqlalchemy.engine.RowProxy:
- classmethod is_subcontract_stats(bpf_data_query)¶
Data for « F - 2. ACTIVITÉ EN PROPRE DE L’ORGANISME »
Gather data for everything that is subcontract
- Renvoie:
info as row attributes : total_hours and headcount
- Rtype sqlalchemy.engine.RowProxy:
- ods_template = '/home/docs/checkouts/readthedocs.org/user_builds/endi/checkouts/latest/docs/source/../../endi/sample_templates/bpf/CERFA 10443*14.ods'¶
- classmethod sum_bpf_datas(bpf_data_query)¶
- classmethod trainee_types_stats(bpf_data_query)¶
Data for « F - 1. TYPE DE STAGIAIRES DE L’ORGANISME »
- Renvoie:
stats for each type of trainee. List indexes match TRAINEE_TYPES order
- Type renvoyé:
list of dict like {“headcount”: 42, “total_hours”: 12}.
- classmethod training_goals_stats(bpf_data_query)¶
Data for « F - 3. OBJECTIF GÉNÉRAL DES PRESTATIONS DISPENSÉES »
- Renvoie:
stats for each type of training goal. List indexes match TRAINING_GOALS order
- Type renvoyé:
list of dict like {“headcount”: 42, “total_hours”: 12}.
- classmethod training_speciality_stats(bpf_data_query)¶
Data for « F - 4. SPÉCIALITÉS DE FORMATION »
- Type renvoyé:
iterator of dicts
- class endi.models.services.bpf.Cerfa_10443_15¶
Bases :
Cerfa_10443_14Contains strictly same data/rules as CERFA 10443*14
- class endi.models.services.bpf.Cerfa_10443_16¶
Bases :
Cerfa_10443_15https://www.formulaires.modernisation.gouv.fr/gf/getNotice.do?cerfaFormulaire=10443&cerfaNotice=50199 https://www.formulaires.modernisation.gouv.fr/gf/cerfa_10443.do
- INCOME_SOURCES = [(0, 'Entreprises pour la formation de leurs salariés', []), (None, 'Organismes gestionnaires des fonds de la formation professionnelle pour des actions dispensées dans le cadre des :', [(1, "contrats d'apprentissage"), (2, 'contrats de professionnalisation'), (3, 'promotion ou reconversion par alternance'), (4, 'congés individuels de formation et des projets de transition professionnelle'), (5, 'compte personnel de formation'), (6, 'dispositifs spécifiques pour les personnes en recherche d’emploi'), (7, 'dispositifs spécifiques pour les travailleurs non-salariés'), (8, 'plan de développement des compétences ou d’autres dispositifs')]), (10, 'Pouvoirs publics pour la formation de leurs agents (Etat, collectivités territoriales, établissements publics à caractère administratif)', []), (None, 'Pouvoirs publics pour la formation de publics spécifiques', [(20, 'Instances européennes'), (21, 'État'), (22, 'Conseils régionaux'), (23, 'Pôle emploi'), (24, 'Autres ressources publiques')]), (30, 'Contrats conclus avec des personnes à titre individuel et à leurs frais', []), (31, 'Contrats conclus avec d’autres organismes de formation (y compris CFA)', []), (32, 'Autres produits au titre de la formation professionnelle continue', [])]¶
- TRAINEE_TYPES = [(0, 'Salariés d’employeurs privés hors apprentis', []), (1, 'Apprentis', []), (2, 'Personnes en recherche d’emploi formées par votre organisme de formation', []), (3, 'Particuliers à leurs propres frais formés par votre organisme de formation', []), (4, 'Autres stagiaires', [])]¶
- TRAINING_GOALS = [(None, 'Formations visant un diplôme ou un titre à finalité professionnelle (hors certificat de qualification professionnelle) inscrit au Répertoire national des certifications professionnelles (RNCP)', [(0, 'Niveau 6 à 8 (Licence, Master, diplôme d’ingénieur, Doctorat…)....'), (1, 'Niveau 5 (BTS, DUT, écoles de formation sanitaire et sociale …) .'), (2, 'Niveau 4 (BAC professionnel, BT, BP, BM…)'), (3, 'Niveau 3 (BEP, CAP…).....'), (4, 'Niveau 2'), (5, 'Certificat de qualification professionnelle (CQP) sans niveau de qualification')]), (10, 'Formations visant une certification (dont CQP) ou une habilitation enregistrée au répertoire spécifique (RS)', []), (11, 'Formations visant un CQP non enregistré au RNCP ou au RS', []), (12, 'Autres formations professionnelles', []), (13, 'Bilan de compétences', []), (14, "Actions d'accompagnement à la validation des acquis d'expérience", [])]¶
- classmethod build_data_dict(bpf_data_query)¶
- ods_template = '/home/docs/checkouts/readthedocs.org/user_builds/endi/checkouts/latest/docs/source/../../endi/sample_templates/bpf/CERFA 10443*16.ods'¶
endi.models.services.business module¶
endi.models.services.business_status module¶
endi.models.services.company module¶
Company query service
- class endi.models.services.company.CompanyService¶
Bases :
object- classmethod employs(company, uid)¶
Check if the given company employs User with id uid
- classmethod format_label_from_datas(company_class, company_datas, with_select_search_datas=False)¶
Return the company’s label to display Add employees infos to company’s name if config ask to Add search datas (employees, code_compta) if asked
- company_datas:
can be either - a Company object - an SqlAlchemy.Row : (
id, name, code_compta, active, nb_employees, employees_list
) - a dict : {
“id”: int, “name”: str, “code_compta”: str, “active”: bool, “nb_employees”: int, “employees_list”: str
}
- classmethod get_active_employees(company)¶
Collect active employees
- classmethod get_cancelinvoices(instance, valid=False)¶
- classmethod get_companies_select_datas(company_class, request, only_active=False)¶
- classmethod get_contribution(company_id, prefix='')¶
- classmethod get_customer_codes_and_names(company)¶
Return a query for code and names of customers related to company :param company: the company we’re working on :returns: an orm query loading Customer instances with only the columns we want :rtype: A Sqlalchemy query object
- classmethod get_customers(instance, year)¶
- classmethod get_employee_ids(company)¶
Collect company user_ids
- classmethod get_estimations(instance, valid=False)¶
- classmethod get_general_customer_account(instance, prefix='')¶
- classmethod get_general_expense_account(instance, prefix='')¶
- classmethod get_general_supplier_account(instance, prefix='')¶
- classmethod get_id_by_analytical_account(company_class, analytical_account)¶
Return id of the oldest company with given analytical account
- Paramètres:
company_class (class) – The Company class
analytical_account (str) – The analytical account to get
- Renvoie:
Integer or None
- classmethod get_invoices(instance, valid=False, not_paid=False)¶
- classmethod get_last_treasury_main_indicator(company)¶
Retrieve the main indicator’s datas from the last treasury grid of a given company Return {« date », « label », « value »} of the measure
- classmethod get_late_invoices(instance)¶
- classmethod get_nb_km_on_period(company, start_date, end_date)¶
Compute the kilometers declared for a given company on the given period
- classmethod get_next_cancelinvoice_index(company)¶
Return the next available sequence index in the given company
- classmethod get_next_estimation_index(company)¶
Return the next available sequence index in the given company
- classmethod get_next_index(company, factory)¶
- classmethod get_next_invoice_index(company)¶
Return the next available sequence index in the given company
- classmethod get_project_codes_and_names(company)¶
Return a query for code and names of projects related to company
- Paramètres:
company – the company we’re working on
- Renvoie:
an orm query loading Project instances with only the columns
we want :rtype: A Sqlalchemy query object
- classmethod get_rate(company_id: int, rate_name: str, prefix: str = '') float¶
Renvoie le taux de contribution à appliquer pour cette enseigne (assurance/contribution ou autre)
Les CustomInvoiceBookEntry module créé par endi ont un « name » qui correspond à l’attribut de Company qui permet d’overrider le taux associé
- Paramètres:
id – Company id
prefix (str) – configuration key prefix (ex: internal)
- classmethod get_rate_level(company_id: int, rate_name: str, prefix: str = '') str¶
Renvoie le niveau (cae/company/document) auquel la contribution est définie
Note : Les CustomInvoiceBookEntry module créé par endi ont un « name » qui correspond à l’attribut de Company qui permet d’overrider le taux associé
- Paramètres:
id – Company id
prefix (str) – configuration key prefix (ex: internal)
- classmethod get_supplier_codes_and_names(company)¶
Return a query for code and names of suppliers related to company :param company: the company we’re working on :returns: an orm query loading Supplier instances with only the columns we want :rtype: A Sqlalchemy query object
- classmethod get_tasks(instance, offset=None, limit=None)¶
- classmethod get_third_party_customer_account(instance, prefix='')¶
- classmethod get_third_party_supplier_account(instance, prefix='')¶
- classmethod get_total_expenses_and_km_on_period(company, start_date, end_date)¶
Compute the expense total HT and the kilometers declared for a given company on the given period
- classmethod get_total_expenses_on_period(company, start_date, end_date)¶
Compute the expense total HT for a given company on the given period
- classmethod get_total_purchases_on_period(company, start_date, end_date)¶
Compute the purchase total HT for a given company on the given period
- classmethod get_turnover(company, start_date, end_date)¶
Compute the turnover for a given company on the given period
- classmethod has_group_member(company, group_name)¶
Check if the company has a trainer in its employees
- Paramètres:
company (obj) – A Company instance
group_name (str) – The name of the group to check for
- Renvoie:
A boolean
- classmethod label_datas_query(company_class, request, only_active=False)¶
- classmethod query_for_select_with_trainer(company_class, request)¶
Build a query suitable for deform select widgets population
- Paramètres:
company_class (class) – The Company class
- Renvoie:
A sqlalchemy query object
endi.models.services.find_company module¶
endi.models.services.mixins module¶
- class endi.models.services.mixins.BusinessLinkedServiceMixin¶
Bases :
objectMethods to be added on a BusinessLinkedModelMixin related service
The inheriting service must be targeting a model that inherits BusinessLinkedModelMixin.
- static linkable(cls, business)¶
Return the objects available for linking with a given business
- Paramètres:
class (parent_model) –
parent_model_company_id_field – the model class attribute holding company link
- Rtype query of BaseExpenseLine:
- static query_linked_to(cls, target: BusinessMetricsMixin)¶
endi.models.services.naming module¶
- class endi.models.services.naming.NamingService¶
Bases :
objectHandles naming overrides per business type
Names sources are (specific to general) : - from Task.frozen_settings attribute (on Task models) - from db (LabelOverride) - default hardcoded labels
- DEFAULT_LABELS = {'cancelinvoice': 'Avoir', 'estimation': 'Devis', 'internalcancelinvoice': 'Avoir interne', 'internalestimation': 'Devis interne', 'internalinvoice': 'Facture interne', 'invoice': 'Facture', 'signed_agreement': 'Bon pour accord'}¶
- SUPPORTED_LABEL_KEYS = ['estimation', 'invoice', 'cancelinvoice', 'internalinvoice', 'internalcancelinvoice', 'internalestimation', 'signed_agreement']¶
- classmethod get_default_label(label_key)¶
- classmethod get_label_for_business_type_id(label_key: str, business_type_id: int) str¶
- Renvoie:
label from LabelOverride if any, default label else.
endi.models.services.official_number module¶
- class endi.models.services.official_number.AbstractNumberService¶
Bases :
objectExpose a method to assign templated and unique numbers to a class instance
Must be implemented once per document type (OfficialNumberMixin child class) that needs its own numbering scheme.
- classmethod allowed_keys()¶
- classmethod assign_number(request, node: OfficialNumberMixin, template)¶
This function should be run within an SQL transaction to enforce sequence index unicity.
- classmethod get_involved_sequences(invoice, template)¶
Tell which sequences are to be used and what indexes they will give
- Renvoie:
the sequences that would be used by this template and their next index
- Type renvoyé:
list of couples [<sequence>, <sequence_number>]
- classmethod get_sequences_map()¶
- returns: must include following keys“SEQGLOBAL”, “SEQYEAR”,
“SEQMONTH”, “SEQMONTHANA”
- classmethod sequences_map()¶
Memoized on first call ; this is to avoid import loops.
- classmethod validate_template(template)¶
Validate the correctness of the invoice number template
endi.models.services.phase module¶
endi.models.services.project module¶
endi.models.services.sale_file_requirements module¶
Service managing file requirements :
Project
Businesses
Tasks (Invoice, Estimation, CancelInvoice)
Has several main responsabilities
query requirement definitions
Populate the Indicators
Handle file events and update the indicators (with cascade)
- class endi.models.services.sale_file_requirements.BusinessFileRequirementService¶
Bases :
SaleFileRequirementServiceManage Business file requirements
- classmethod check_status(node)¶
Collect indicators related that concerns the given node
- class endi.models.services.sale_file_requirements.ProjectFileRequirementService¶
Bases :
SaleFileRequirementServiceManage Project file requirements
Collect indicators related that concerns the given node
- classmethod populate(node)¶
Generate SaleFileRequirement instances for the given node
- Paramètres:
node (obj) – A
endi.models.node.Nodeinstance
related to the sale module
- class endi.models.services.sale_file_requirements.SaleFileRequirementService¶
Bases :
object- classmethod force_all(node)¶
Force all indicators that are not successfull
- Paramètres:
node (obj) – The associated node
- classmethod get_attached_indicators(node, file_type_id=None)¶
Get all the indicators attached to the given node
Return indicators related to the given file object
Collect indicators related that concerns the given node
- classmethod on_file_add(node, file_object)¶
- classmethod on_file_remove(node, file_object)¶
- classmethod on_file_update(node, file_object)¶
- classmethod populate(node)¶
Generate SaleFileRequirement instances for the given node
- Paramètres:
node (obj) – A
endi.models.node.Nodeinstance
related to the sale module
- classmethod register(node, file_object, action='add')¶
Update the Indicators attached to node if one is matching the file_object
- Paramètres:
node (obj) – A
endi.models.node.Nodeinstance
related to the sale module :param obj file_object: A
endi.models.files.Fileinstance that has juste been uploaded :param str action: add/update/delete
- class endi.models.services.sale_file_requirements.TaskFileRequirementService¶
Bases :
SaleFileRequirementService- classmethod check_status(node)¶
- classmethod get_other_attachments(node)¶
List files that are attached to the node but not related to any indicator
Collect indicators that concerns the current Task
- endi.models.services.sale_file_requirements.build_indicator_from_requirement_def(business_type_file_type_req: BusinessTypeFileType, node: Node) Optional[SaleFileRequirement]¶
Initialize an indicator from the given req definition object
Handles dispatch of indicators on the upper levels
from Task to Business/Project
from Business to Project
endi.models.services.user module¶
- class endi.models.services.user.UserPrefsService¶
Bases :
objectHandles account.user_datas field
That field is a melting-pot for user preferences and things we want to remmember at user scope.
Limitation : properties are stored as text JSON, thus, it has no structure from MySQL standpoint and this is not possible to filter on it at SQL level.
- DEFAULT_VALUES = {'expense': {'bookmarks': {}}, 'last_managed_company': None}¶
- classmethod get(request, key)¶
- classmethod set(request, key, value)¶