Development Processes

 

Guide to Making Software Changes

This document describes the core development guidelines for contributing to the xTuple development effort. It assumes very little about software development experience but is not a tutorial for software development, software development tools, or programming languages. Most of the content will be familiar to experienced software developers.

The current draft is aimed at employees of xTuple working internally. Future versions will address the processes for customer, reseller, and third-party contributions.

The reader should read and follow the steps outlined in the Development Environment Setup guide before continuing with the steps below. The configuration document describes what tools you will need and how to obtain and install them.

Check with Trolltech to see if you need to get a commercial license for Qt.

Conventions:

  • .../name: The path to reach a certain file or directory. This may be a full- or relative-path. If the path starts with a slash (/) then you must specify the full path (this is rare).
  • prompt$ stuff: $ and anything before it is the prompt and stuff is what you type after it

Introductory Concepts

master copy of something vs. the copy that's actually used

the appropriate place(s) to make a change visible

what is part of the product and what is not

bug tracking

what are SVN and CVS?

SVN repository holds xtuple, xtupledocs, xtupleserver, updater, csvimport, openrpt on SourceForge

Read-access to the SourceForge repositories is available to everyone while write/commit access is restricted. If you want commit access, please contact xTuple.

There is a private repository for OpenMFG client and server files

how we use CVS and SVN: if you check in, everyone sees it when they update

naming conventions

backing out changes if you've really screwed up

if it's broke, fix it; if it ain't broke, don't break it

use the language to simplify

images in the application

Changes Independent of xTuple ERP

one-off changes vs. experimental work vs. not generally applicable

don't do it - maintenance - but if you must, create your own CVS or SVN repository for your own work and keep each feature or bug-fix isolated to individual checkins. There are strategies for updating your own repository from a master and keeping your changes.

Fixing Bugs

reproduce

confirm

assign

resolve - checkin as few times as possible (combine contents of multiple directories) and the comment should include "fixes bug #12345" or "fixes issue #12345" if it really fixes the problem, or leave off the word "fixes" if it's only part of the solution, such as an intermediate checkin. This wording automatically updates the Mantis issue, adding a note in all of these cases and actually marking the issue as resolved if the comment includes the word "fixes". Note that the # symbol is significant, as is the fact that there should be no space between the # and the issue number.

close

Adding Features

understand

add issue

spec

implement

resolve

accept

close

Some General Guidelines

If the code you're changing is broken (in some way other than what you're trying to change or fix), fix it anyway. There are only two exceptions:

  1. You know for a fact that someone else is working on fixing this problem.
  2. The product is approaching final release, as in you are making changes to a late beta release, a release candidate, or a final build.

If you are making additions to existing code, integrate your changes with the existing code. For example, if an existing stored procedure manipulates work orders with a status of Open and Exploded and you are trying to make it do the same thing with Imploded work orders, don't do this:

IF (_statusVar IN (O, E) THEN -- existing
...                           -- existing
ELSEIF (_statusVar = I) THEN
same ... -- duplicated code: Bad Programmer!

Do this instead:

IF (_statusVar IN (O, E, I) THEN
...

Changing Reports

Master copies of all reports live in the share/reports subdirectory of the xtuple repository.

  1. svn update your xtuple repository checkout
  2. Load reportname.xml into the database
  3. Make and test your changes
  4. Save your changes to the database as level 0 of the report
  5. Save your changes to
    .../OpenMFG/ReportDefinitions/OpenMFG/reportname.xml
  6. If you had to use a level other than 0 for testing, remove the non-level 0 copy of the report from the database.
  7. svn diff reportname.xml and review the changes manually to make sure they look right
  8. svn commit reportname.xml

    Put a short description of why you made this change in your checkin comment, including the Mantis issue number if there is one. The 'what' is clear from the differences between the previous version and what you checked in.

If this change is related to a Mantis issue, see the Fixing Bugs or Adding Features sections for further guidance.

Changing the GUI Client

One of the things we're trying to do to the existing code in OpenMFG is move the SQL out of the source code, particularly the more complex MetaSQL queries, and into a separate resource file which is imported into the database. This will eventually allow for patching some bugs without shipping whole binary packages, sharing queries between source files, and other neat things. To implement queries as resources:

  1. Change directory to the metasql directory (e.g. cd xtupleserver/dbscripts/metasql).
  2. Edit group-name.mql -- where group = the type of information (e.g. arHistory, inventoryHistory, salesOrderItems) and name = a qualifier for how the information might be used (e.g. detail, populate). Put the query, including MetaSQL tags if necessary, in this .mql file. The first three lines of the file must be comments that define the group, name, and notes associated with the .mql file. For example:
    -- Group:arHistory
    -- Name:detail
    -- Notes:used by arWorkBench, dspAROpenItems
  3. Import the .mql file into the database using the openrpt/bin/importmqlgui utility.
  4. In the C++ source file that needs to call this query:
    #include <metasql.h>
    #include "mqlutil.h"
    ...
    // in the method that calls the query
    ParameterList params; // if there are MetaSQL parameters to set then
    setParams(params); // either have a method that sets them or set them inline here
    MetaSQLQuery mql = mqlLoad("group", "name"); // group and name defined in the .mql file comments
    XSqlQuery myQuery = mql.toQuery(params);
    if (myQuery.first())
    ...
  5. Rebuild the application and test.

Adding Custom Widgets

Guidelines for developing widgets haven't yet been codified.

There are several steps required to implement a new widget for use in the application and make it visible in Qt Designer. Here they all are:

  1. Create the widget.cpp, widget.h, and possibly widget.ui files that implement your new widget in the widgets directory. The widget.h filename must be all lowercase regardless of the capitalization of widget.cpp or the class name. You should use all lowercase letters to name the file.
  2. Create the widget's plug-in widgetplugin.h file in the widgets/plugins directory. Copy and edit an existing plug-in header file to make sure you get all of the required information. If widget.cpp and widget.h implement more than one custom widget that you want visible in Qt Designer, create separate plug-in header files for each widget.
  3. Edit the widgets.pro file and add widgetplugin.h file(s) to the first HEADERS list, widget.cpp to the SOURCES list, and widget.h file to the second HEADERS list.  If your widget includes a .ui file, add this to the FORMS list.
  4. Edit widgets.cpp and add an #include for widgetplugin.h and add an m_plugins.append() for the plug-in class.
  5. Rebuild the Makefiles in the widgets directory:
    cd widgets
    rm Makefile*
    qmake
  6. Quit Qt Designer if you have it running.
  7. From the top source directory, not the widgets subdirectory, build the application:
    cd ..
    make #or mingw32-make or ...

    You may have to remove the old plug-in shared library manually for this to work. The plug-in shared library is named something like

    $QTDIR/plugins/designer/libxtuplewidgets.shared-library-suffix.
  8. Start Qt Designer.

Changing the Database Structure

The PostBooks and OpenMFG applications use very similar databases. The majority of tables, views, triggers, and stored procedures are shared. The xtupleserver SVN module holds scripts to create these shared views, triggers, and stored procedures. In addition, the scripts used to update individual aspects of the database structure from one release to the next, e.g. to add table columns or indexes, are also stored in the xtupleserver module. Any functionality or changes specific to OpenMFG should be checked in to the appropriate repository.

Here are the conventions for SQL scripts used to define or change aspects of the database structure:

  • File names should end with the suffix .sql
  • File names should consist entirely of lowercase letters except as noted below.
  • Files which change the structure of existing tables should be named alterTablename.sql - note the uppercase letter at the beginning of the table name.
  • Files which add tables, privileges, and indexes should be named createShortdescrip.sql - again note the one uppercase letter in the middle.
  • Create explicit transactions for alter and create scripts that have multiple lines in them. Use COMMIT to close these transactions, never the PostgreSQL extension END.

  • If you need to create a new database object then call the dropIfExists stored procedure before the CREATE line. This stored procedure knows how to delete tables, views, and triggers as of release 3.0, and constraints as of release 3.1. For example, if you are adding a new view for vendors to the apischema then start with the following:

    BEGIN;
    SELECT dropIfExists('VIEW', 'vendor', 'api');
    CREATE VIEW api.vendor ...
  • Disable triggers before running ALTER TABLE if possible. This will prevent problems where updates to tables cause triggers to execute and potentially fail because of alterations to one or more tables. This can be skipped if there is reason to do so but if you don't disable the triggers then document the required specific order of script execution.
    ALTER TABLE table DISABLE TRIGGER ALL;
    -- make changes here
    ALTER TABLE table ENABLE TRIGGER ALL;
  • Create a precheck.xml or add to an existing precheck.xml file a SELECT statement to search for any data that might cause a database upgrade to fail. This SELECT statement should return TRUE if the data can be successfully upgraded and FALSE if not. For example, if changing a column to a foreign key, the precheck statement should query that column and return TRUE if all values in the existing data meet the foreign key requirement and FALSE if some values do not refer to existing records. An example Precheck.template file is available in xtupleserver/updateScripts.

Changing Stored Procedures

Do not extract a stored procedure from a database to edit it; there are several reasons why this is a bad idea. Here is the correct process to follow:

  1. update your xtupleserver and OpenMFG-specific checkouts.
  2. change to the dbscripts/functions directory
  3. Find the file that contains the stored procedure(s) you need to change. Each file should be named after the stored procedure it contains.
  4. Make and test your changes to the stored procedure file. To test them, you will need to load your changes into the database. One way to do this is with the psql command line tool:
    $ psql
    Password:
    database=# \i storedprocfilename
  5. svn diff storedprocfilename and review the changes manually to make sure they look right
  6. svn commit storedprocfilename

    Put a short description of why you made this change in your checkin comment, including the Mantis issue number if there is one. The 'what' is clear from the differences between the previous version and what you checked in.

If this change is related to a Mantis issue, see the Fixing Bugs or Adding Features sections for further guidance.

Style:

Use IF ... ELSIF ... ENDIF; as much as possible. It's much easier to code correctly and maintain than IF ... ELSE IF ... ENDIF; ENDIF;

The preferred quoting method to wrap the body of a stored procedure is $$ quoting. Previously single-quoting alternatives were used to work with all of the versions of PostgreSQL that our customers use; however this is no longer a requirement and the $$ quoting is easier to read.

Changing Documentation

You may also want to edit the documentation, some of which is written in XML using DocBook for markup; some is written using Drupal books.

Adding Images to the application

First read Qt's documentation on the Resource Compiler (rcc). Here are the xTuple conventions:

  • Try to use a PNG or XMP file for your image.
  • Put the image file in the images subdirectory of the source code directory where the image is used by the application.
  • If there isn't already a Qt Resource (.qrc) file in the source code directory or in the images subdirectory, create one and name it after the directory in which you put it (e.g. guiclient.qrc)

Make sure the resource path referred to by the source code matches the resource path in the .qrc file.

 
jaufrec's picture
Offline
Joined: 05/06/2009
How to compile

Unless I'm missing something, the instructions to actually compile, which I expected to find on this page, are in the file DevelopmentOverview.pdf in
http://sourceforge.net/project/downloading.php?group_id=196195&filename=...

That zip has three PDFs, and two of them are the same as the previous page (Development Environment Setup) and this page, but DevelopmentOverview doesn't seem to have a matching page.

 

mead