mercredi 31 janvier 2018

build a report using a query - Dynamics NAV

 how to build a report using a query

Much to my disappointment, I discovered that reports did not allow using query as a data item. So I started thinking on how to get around it.
Then I remembered our old friend, the integer table.
If you build a report using the integer as the data item, you can then build code to process a query one row at a time for each integer. After the query has read the last row, you simply execute a CurrReport.BREAK.
I have attached a simple sample query and report that show how easy this is to do.
Steps:
Step 1: choose or design a query
Step 2: design new report
Step 3: Add DataItem Integer - change the name to something meaningful (CustomerOrderTotals)
Step 4: define global variables to be used for each query field you will be using in the report and the Query Name
Step 5: under DataItem define your columns using the above defined global variables
Step 6: View C/AL Code (F9)
Step 7: OnPreDataItem trigger add code - QueryName.OPEN;
Step 8: OnAfterGetRecord trigger - add code
IF NOT QueryName.READ THE CurrReport.BREAK;
Variable1:=QueryName.Variable1;
Variable1:=QueryName.Variable2;
repeat lines for remaining fields
Step 9: exit code and view layout
Step 10: design your report in the Visual Layout editor, exit, and save, then save and compile your report and run.

nice Blog Post by Dénis Yougang
(Cf David Machanick)

lundi 29 janvier 2018

MICROSOFT DYNAMICS NAV (RECORD DELETION)



OUTIL DE SUPPRESSION DE DONNEES POUR DYNAMICS NAV (RECORD DELETION)

Cet outil de suppression de données est utile si vous voulez «nettoyer» dans une Société sur Microsoft Dynamics NAV des données transactionnelles. Il se peut par exemple que vous ayez testé des transactions dans une société que vous souhaitez utiliser pour une mise en production ou que vous souhaitiez simplement avoir une société propre sans transactions pour une démonstration, une formation ou une session de test.

Importer l’objet global « DYRD18.1 » joint à ce document, contenant les objets qui sont tous autonomes dans la gamme 50090. Vous aurez besoin d'une licence développeur pour supprimer les enregistrements dans les tables protégées.



Une fois les objets importés et synchronisés dans la base de données, le menu est visible dans Département : (cf image ci-dessous)
NB : les Objets importés ne créent pas le menu comme présenté sur les images ci-dessous. Il faudra si utiles pour celui qui veux l’utiliser, créer cela et éventuellement un rôle dédié à cela.











Exécutez la page 50090, puis cliquez sur « Insérer / Mettre à jour les table ». Cela remplira la liste avec toutes les tables qui se trouvent dans la base de données. Si vous ajoutez ensuite de nouvelles tables, vous pouvez ré exécuter cette fonction pour les ajouter.



Ensuite, vous parcourez et sélectionnez les tables dont vous voulez supprimer les enregistrements en cochant le champ “Delete Records”. La fonction appelée “Suggest Records to delete” sélectionnera les tables dont vous souhaitez généralement supprimer les enregistrements lors du nettoyage d'une entreprise à partir de données transactionnelles. Notez que la sélection de tables dans cette fonction est basée sur une version W1 de Dynamics NAV 2015. Si vous disposez d'une version localisée, de modules complémentaires ou de personnalisations, vous devrez passer en revue ces tables et sélectionner manuellement des tables supplémentaires pour supprimer des enregistrements. . Notez également que je ne suis pas responsable si cette suggestion sélectionne quelque chose que vous ne voulez pas supprimer ou ignore quelque chose que vous voulez supprimer



La fonction "Clear Records to delete" supprime toutes les sélections.



Lorsque vous êtes satisfait de la sélection, appuyez sur “Delete Records”. Dynamics NAV passe maintenant par les tables et supprime tous les enregistrements de chacune des tables sélectionnées. Il peut être judicieux de faire une sauvegarde des données avant de faire cela. Normalement, je copie juste la société avant cette étape, ainsi au moins vous avez une société qui peut facilement être reconstituée ou copier / coller des données.



Une fois les enregistrements supprimés, il est recommandé de vérifier les tables qui contiennent encore des données pour vous assurer que vous n'avez rien oublié. La façon la plus simple de le faire est d'appliquer un filtre sur le champ « No. of Records » <> 0 et d'utiliser la fonction “ View Records ” pour afficher les enregistrements dans les tables.



Lorsque vous sélectionnez « View Records », la table sera exécutée pour afficher tous les enregistrements et tous les champs, comme ci-dessous






Lorsque l'on regarde les enregistrements, il est généralement facile de voir s'ils auraient dû être supprimés ou non, si les enregistrements ont un numéro d'entrée, un numéro de document, etc., il s'agit probablement de données transactionnelles qui devraient être supprimées. Le nombre d'enregistrements dans le tableau peut parfois aussi vous donner un indice s'il doit être supprimé ou non.
L'option suivante lors de l'examen des données restantes consiste à utiliser la fonction "Check Table Relations". Cette fonction parcourt tous les enregistrements et utilise le champ "relations defined" dans la table de champ dans NAV et valide les relations de table en regardant simplement si l'enregistrement lié est dans la base de données ou non. Notez que ceci vérifie seulement les relations très simples où un champ a une relation de table avec un champ dans une autre table (semblable aux relations de table que vous trouvez dans le "FactBox" dans la feuille de configuration). Il ne vérifie pas les relations de table impliquant plusieurs champs ou relations de table conditionnelles. Mais c'est encore une bonne vérification je pense.

Après la vérification des relations de la table, vous pouvez définir un filtre sur le “No. of Table Relations Errors” d’être <> 0 et vous devriez voir s'il y a des erreurs de relation de table de base
(#Image filtring on No. of Table Relations Error <>0)
S'il y a des erreurs, vous pouvez faire une recherche sur le numéro pour voir les erreurs. Dans l'exemple ci-dessous, vous voyez que les codes d'agent d'expédition «DHL» et «UPS» figurent sur certains clients, mais ils n'existent pas dans la table Agent d'expédition.



Comme mentionné ci-dessus, la vérification de la relation entre les tables ne fait que des vérifications de base, donc ne comptez pas trop sur elle. Si vous avez une grande quantité de données de base, cela peut prendre un certain temps.
Comme une note de côté; Si vous préparez une base de données pour la mise en ligne comme celle-ci, n'oubliez pas de revoir et de réinitialiser les souches de numérotation. Et n'oubliez pas de toujours tester le résultat final.

FIN!!!!!!!!!!!!!!!!!!!

jeudi 25 janvier 2018

Workflow Editing in Odoo

A workflow is a technical artifact which manages a set of “things to do” associated to the records of any model. More specifically, a workflow is a directed graph where the nodes are called “activities” and the arcs are called “transitions”.


Odoo workflow provides:
– a description of the evolution of a record (document) over time
– automatic actions based on various and flexible conditions
– management of company roles and validation steps
– management of interactions between objects
– a visual representation of document flows through their lifecycle

Note:
When customizing a workflow, be sure you do not modify an existing node or arrow, but rather add new nodes or arrows. If you absolutely need to modify a node or arrow, you can only change fields that are empty or set to the default value. If you don’t do that, your customization will be overwritten at the next update or upgrade to a future version of Odoo.

Example:
If Total Amount of Quotation is less than or equals to 1000rs then directly make a purchase order otherwise it should first ask for confirmation if total amount is greater than 1000.

Steps:
First of all, if the user doesn’t have access to technical features then you have to give him access.
Go to Settings click on Users, then edit the user, in access rights tab, check Technical Features and save.Reload your page. Now you will have access to a new Technical menu on left Sub-menu Panel.

1) Go to Settings click on Workflows

2) Select Purchase Order Basic Workflow

3) Switch to Diagram View

A) New Node
Name:- validatequotation.
B) Drag Lines between Nodes and Create Transactions




a)Draft-to-validatequotation.
Signal Button:- BLANK
Condition:- amount_total>=1000

b)Draft-to-confirmed.
Signal Button:- BLANK
Condition:- amount_total<1000

c)validatequotation-to-confirmed.
Signal Button:- purchase_confirm
Condition:- True

Now, try to create purchase order with both the conditions and see the changes.

Workflow in Odoo

<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="wkf_sale" model="workflow">
<field name="name">sale.order.basic</field>
<field name="osv">sale.order</field>
<field name="on_create">True</field> <!-- ?? -->
</record>
<record id="act_sent" model="workflow.activity">
<field name="wkf_id" ref="wkf_sale"/>
<field name="name">sent</field>
<field name="flow_start">True</field> <!-- seulement pr l'étape de départ -->
<field name="flow_stop">True</field> <!-- Seulement pr l'étape d'arrivée -->
<field name="kind">function</field> <!-- = dummy par defaut (dummy = n'exécute aucun code -->
<field name="action">write({'state':'sent'})</field> <!-- Code exécuté à l'ARRIVE sur l'étape -->
OU
<field name="action">action_invoice_create()</field> <!-- le proto de la fonction est alors : action_invoice_create(self, cr, uid, ids, context=None): -->
<field name="split_mode">XOR</field> <!-- ça fait quoi ?? -->
<field name="join_mode">AND</field> <!-- ???? -->
</record>
<record id="trans_sent_cancel" model="workflow.transition">
<field name="act_from" ref="act_sent"/>
<field name="act_to" ref="act_cancel"/>
<field name="signal">cancel</field> <!-- ce signal peut être appelé par un bouton SANS type='' ou via du code wf_service.trg_validate(uid, 'sale.order', sale_id, 'cancel', cr) -->
<!-- ATTENTION : soit on met un signal, soit on met une condition (avec un trigger éventuel en plus), mais pas les deux a priori -->
<field name="trigger_model">procurement.order</field>
<field name="trigger_expr_id">procurement_lines_get()</field> <!-- Cette fonction doit être sur l'objet du workflow, avec un proto def procurement_lines_get(self, cr, uid, ids, *args) -->
<field name="condition">test_state('finished')</field> <!-- test_state(self, cr, uid, ids, mode, *args) sur l'objet du trigger_model et il passera mode='finished'
doit renvoyer True ou False -->
OU
<field name="condition">test_paid()</field> <!-- proto de la fonction : self, cr, uid, ids, *args)
</record>

# 2 méthodes pour faire avancer manuellement un workflow :

#1) <button name="po_wait_conf" SANS type= => le "name" doit correspondre au "signal" de la workflow.transition
# Dans cette solution, on met l'écriture du nouveau "state" dans la fonction action de la workflow.activity

# Avantage de la solution 1) : simplicité.

#2) <button name="action_button_confirm" type="object"

#et on définit la fonction action_button_confirm dans le code :

#def action_button_confirm(self, cr, uid, ids, context=None):
# self.write( {'state': truc})
# wf_service = netsvc.LocalService("workflow")
# wf_service.trg_validate(uid, 'sale.order', ids[0], 'my_signal', cr)
# où my_signal est celui de la transition qui permet de faire avancer le workflow a l'étape suivante

# Dans cette solution, la action de la workflow.activity d'arrivée est a priori vide, vu que le write du 'state' a été fait dans la fonction.

# Avantage de la solution 2) : la fonction action_button_confirm peut retourner une nouvelle vue.


Champ "condition" sur une transition de workflow :
=================================================
When an activity has been completed, its outgoing transitions are inspected to determine whether it is possible for the workflow instance to proceed through them and reach the next activities. When only a condition is defined (i.e., no signal or trigger is defined), the condition is evaluated by OpenERP, and if it evaluates to True, the worklfow instance progresses through the transition. If the condition is not met, it will be reevaluated every time the associated record is modified, or by an explicit method call to do it.

By default, the attribute condition (i.e., the expression to be evaluated) is just "True", which trivially evaluates to True.

Triggers sur une transition de workflow
=======================================
With conditions that evaluate to False, transitions are not taken (and thus the activity it leads to is not processed immediately). Still, the workflow instance can get new chances to progress across that transition by providing so-called triggers. The idea is that when the condition is not satisfied, triggers are recorded in database. Later, it is possible to wake up specifically the workflow instances that installed those triggers, offering them to reevaluate their transition conditions. This mechanism makes it cheaper to wake up workflow instances by targetting just a few of them (those that have installed the triggers) instead of all of them.

Triggers are recorded in database as record IDs (together with the model name) and refer to the workflow instance waiting for those records. The transition definition provides a model name (attribute trigger_model) and a Python expression (attribute trigger_expression) that evaluates to a list of record IDs in the given model. Any of those records can wake up the workflow instance they are associated with.

Proto des fonctions de trigger : self, cr, uid, ids, *args

on prend en argument les IDS de l'objet du workflow
On donne en retour les IDS du trigger_model
=> ce qui est un peu nul, on aurait imaginé l'inverse

Comment ça marche ?
En fait, il faut qu'il y ait un appel explicite à la fonction trg_trigger() :
wf_service = netsvc.LocalService("workflow")
wf_service.trg_trigger(uid, 'account.move.line', id, cr)

cela va appeler toutes les fonctions de trigger liées à l'objet 'account.move.line'
ces fonctions vont renvoyer les IDs des account.move.line

Pour re-tester une condition d'une transition :
wf_service.trg_write(uid, 'purchase.order', purchase.id, cr)
Il va alors appeler la condition et avancer dans la workflow si la condition renvoie True