Explorar o código

Tests for the upcoming application server.

mingodad %!s(int64=13) %!d(string=hai) anos
pai
achega
7f6602d06a

+ 75 - 0
ourbiz/app-config-gui.fl

@@ -0,0 +1,75 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.0300 
+i18n_type 1 
+i18n_include i18n_function.h 
+i18n_function _tr 
+header_name {.h} 
+code_name {.cxx}
+decl {\#include "My_Base_App.h"} {public global
+} 
+
+widget_class AppConfigEditWindow {
+  label {Application Configuration List / Edit} open
+  xywh {730 45 500 494} type Double labelsize 16 resizable
+  class Edit_Base_Window visible
+} {
+  Fl_Browser grid {
+    xywh {5 5 490 200} type Multi labeltype NO_LABEL labelsize 16 textsize 16 resizable
+    class Fl_Data_Table
+  }
+  Fl_Group editGroup {open
+    xywh {5 215 490 269} box ENGRAVED_BOX color 246 labelsize 16 align 8
+  } {
+    Fl_Output db_config_id {
+      label ID
+      macro_name {db config id}
+      xywh {15 240 82 26} labelsize 16 align 5 textsize 16
+      code0 {=add_input_field_to_map("$(1)", "$(2)", $(name));}
+    }
+    Fl_Output db_config_cdate {
+      label CDate
+      macro_name {db config cdate}
+      xywh {115 240 120 25} labelsize 16 align 5 textsize 16
+      code0 {=add_input_field_to_map("$(1)", "$(2)", $(name));}
+    }
+    Fl_Output db_config_mdate {
+      label MDate
+      macro_name {db config mdate}
+      xywh {255 240 120 25} labelsize 16 align 5 textsize 16
+      code0 {=add_input_field_to_map("$(1)", "$(2)", $(name));}
+    }
+    Fl_Check_Button db_config_is_active {
+      label Active
+      macro_name {db config is_active}
+      xywh {385 242 100 23} down_box DOWN_BOX labelsize 16
+      code0 {=add_input_field_to_map("$(1)", "$(2)", $(name));}
+    }
+    Fl_Input db_config_key {
+      label Key
+      macro_name {db config key}
+      xywh {15 292 350 25} labelsize 16 align 5 textfont 1 textsize 16
+      code0 {=add_input_field_to_map("$(1)", "$(2)", $(name));}
+    }
+    Fl_Input db_config_value {
+      label Value
+      macro_name {db config value} selected
+      xywh {15 345 350 25} labelsize 16 align 5 textfont 1 textsize 16
+      code0 {=add_input_field_to_map("$(1)", "$(2)", $(name));}
+    }
+    Fl_Choice dbAction {
+      dirty_name {@dbAction} open
+      xywh {380 310 105 25} down_box BORDER_BOX labeltype NO_LABEL labelsize 16 textsize 16
+    } {}
+    Fl_Button btnDbAction {
+      label Action
+      dirty_name {@btnDbAction}
+      xywh {380 345 105 25} labelsize 16
+    }
+    Fl_Input db_config_notes {
+      label Notes
+      macro_name {db config notes}
+      xywh {15 398 470 76} type Multiline labelsize 16 align 5 textsize 16
+      code0 {=add_input_field_to_map("$(1)", "$(2)", $(name));}
+    }
+  }
+} 

+ 65 - 0
ourbiz/base-report-A4.nut

@@ -0,0 +1,65 @@
+//class BaseReportA4 extends Fl_Group {
+class BaseReportA4 extends Fl_Window {
+	rpt_Logo=null;
+	rpt_Title=null;
+	rpt_SubTitle=null;
+	rpt_Body=null;
+	rpt_SubFooter=null;
+	rpt_Footer=null;
+	
+constructor() {
+	base.constructor(10, 50, 420, 594, _tr("BaseReportA4"));
+begin();
+{ rpt_Logo = new Fl_Box(10, 5, 105, 35, _tr("Ourbiz"));
+  rpt_Logo->labeltype(FL_SHADOW_LABEL);
+  rpt_Logo->labelfont(3);
+  rpt_Logo->labelsize(30);
+  rpt_Logo->align((644|FL_ALIGN_INSIDE));
+} // Fl_Box* rpt_Logo
+{ rpt_Title = new Fl_Box(120, 5, 295, 20, _tr("Report Title"));
+  rpt_Title->labelfont(1);
+  rpt_Title->labelsize(16);
+} // Fl_Box* rpt_Title
+{ rpt_SubTitle = new Fl_Box(120, 30, 290, 10, _tr("Date"));
+  rpt_SubTitle->labelsize(8);
+  rpt_SubTitle->align((FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
+} // Fl_Box* rpt_SubTitle
+{ local o = new Fl_Box(10, 40, 405, 1, _tr("Line"));
+  o->box(FL_FLAT_BOX);
+  o->color(34);
+  o->labeltype(FL_NO_LABEL);
+} // Fl_Box* o
+{ local o = rpt_Body = new Fl_Data_Table(10, 45, 408, 495);
+  rpt_Body->box(FL_NO_BOX);
+  rpt_Body->color(FL_BACKGROUND2_COLOR);
+  rpt_Body->selection_color(FL_SELECTION_COLOR);
+  rpt_Body->labeltype(FL_NORMAL_LABEL);
+  rpt_Body->labelfont(0);
+  rpt_Body->labelsize(8);
+  rpt_Body->labelcolor(FL_FOREGROUND_COLOR);
+  rpt_Body->textsize(8);
+  rpt_Body->align((FL_ALIGN_BOTTOM));
+  rpt_Body->when(FL_WHEN_RELEASE_ALWAYS);
+  Fl_Group.current()->resizable(rpt_Body);
+  o->has_scrollbar(FLVS_NONE);
+  o->feature_remove(FLVF_ROW_SELECT | FLVF_PERSIST_SELECT);
+  o->_forPrint = true;
+} // Fl_Data_Table* rpt_Body
+{ local o = new Fl_Box(10, 545, 405, 1, _tr("Line"));
+  o->box(FL_FLAT_BOX);
+  o->color(34);
+  o->labeltype(FL_NO_LABEL);
+} // Fl_Box* o
+{ rpt_SubFooter = new Fl_Box(10, 547, 405, 10, _tr("Page"));
+  rpt_SubFooter->labelfont(1);
+  rpt_SubFooter->labelsize(8);
+  rpt_SubFooter->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
+} // Fl_Box* rpt_SubFooter
+{ rpt_Footer = new Fl_Box(10, 560, 405, 19, _tr("OURBIZ is an excelente application to manage a business."));
+  rpt_Footer->labelfont(2);
+  rpt_Footer->labelsize(8);
+  rpt_Footer->align((129|FL_ALIGN_INSIDE));
+} // Fl_Box* rpt_Footer
+end();
+}
+}

+ 537 - 0
ourbiz/edit-entity-window.nut

@@ -0,0 +1,537 @@
+class Fl_Progress extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+class EditEntitiesWindow extends MyBaseWindow {
+	db_entities_id=null;
+	db_entities_name_ro=null;
+	db_entities_mdate=null;
+	db_entities_cdate=null;
+	tabs=null;
+	tabMain=null;
+	db_entities_name=null;
+	db_entities_company=null;
+	db_entities_address=null;
+	db_entities_zip=null;
+	db_entities_city=null;
+	db_entities_state=null;
+	db_entities_country=null;
+	db_entities_tax_number=null;
+	db_entities_show_on_sales=null;
+	db_entities_show_on_buys=null;
+	db_entities_is_active=null;
+	db_entities_phone=null;
+	db_entities_fax=null;
+	db_entities_use_sales_tax2=null;
+	db_entities_email=null;
+	db_entities_sales_tax_exempt=null;
+	db_entities_web=null;
+	db_entities_irpf_pct_retention=null;
+	db_entities_contact=null;
+	db_entities_gps_coordinates=null;
+	btnDbAction=null;
+	dbAction=null;
+	tabNotes=null;
+	db_entities_notes=null;
+	tabTags=null;
+	db_entities_tags=null;
+	tabGroups=null;
+	db_entities_group_id=null;
+	tabTotals=null;
+	db_entities_credit_allowed=null;
+	db_entities_balance=null;
+	db_entities_sales_quoted=null;
+	db_entities_sales_ordered=null;
+	db_entities_sales_delivered=null;
+	db_entities_sales_invoiced=null;
+	db_entities_sales_discount=null;
+	db_entities_sales_paid=null;
+	db_entities_buys_quoted=null;
+	db_entities_buys_ordered=null;
+	db_entities_buys_received=null;
+	db_entities_buys_invoiced=null;
+	db_entities_buys_paid=null;
+	db_entities_buys_discount=null;
+	tabChartStatistics=null;
+	tabHistory=null;
+	tabReports=null;
+	btnEntitesListContactReport=null;
+	print_progress=null;
+	
+	constructor(){
+		base.constructor(10, 50, 800, 560, "Edit Entity");
+		//clear_flag(GROUP_RELATIVE);
+begin();
+this->box(FL_FLAT_BOX);
+this->color(FL_BACKGROUND_COLOR);
+this->selection_color(FL_BACKGROUND_COLOR);
+this->labeltype(FL_NO_LABEL);
+this->labelfont(0);
+this->labelsize(14);
+this->labelcolor(FL_FOREGROUND_COLOR);
+this->align(FL_ALIGN_TOP);
+this->when(FL_WHEN_RELEASE);
+{ db_entities_id = new Fl_Output(5, 5, 96, 25);
+  db_entities_id->labeltype(FL_NO_LABEL);
+  db_entities_id->labelsize(16);
+  db_entities_id->textsize(16);
+  add_input_field_to_map("entities", "id", db_entities_id);
+} // Fl_Output* db_entities_id
+{ db_entities_name_ro = new Fl_Output(110, 5, 545, 25);
+  db_entities_name_ro->labeltype(FL_NO_LABEL);
+  db_entities_name_ro->labelsize(16);
+  db_entities_name_ro->textsize(16);
+} // Fl_Output* db_entities_name_ro
+{ db_entities_mdate = new Fl_Output(666, 5, 130, 25);
+  db_entities_mdate->tooltip(_tr("This record last update date"));
+  db_entities_mdate->labeltype(FL_NO_LABEL);
+  db_entities_mdate->labelsize(16);
+  db_entities_mdate->textsize(16);
+  add_input_field_to_map("entities", "mdate", db_entities_mdate);
+} // Fl_Output* db_entities_mdate
+{ db_entities_cdate = new Fl_Output(665, 35, 130, 25);
+  db_entities_cdate->tooltip(_tr("This record creation date"));
+  db_entities_cdate->labeltype(FL_NO_LABEL);
+  db_entities_cdate->labelsize(16);
+  db_entities_cdate->textsize(16);
+  add_input_field_to_map("entities", "cdate", db_entities_cdate);
+} // Fl_Output* db_entities_cdate
+{ tabs = new Fl_Tabs(5, 35, 790, 521);
+  tabs->selection_color(4);
+  tabs->labelsize(16);
+  tabs->labelcolor(FL_BACKGROUND2_COLOR);
+  { tabMain = new Fl_Group(5, 62, 790, 494, _tr("Main"));
+    tabMain->color(246);
+    tabMain->labelsize(16);
+    { db_entities_name = new Fl_Input(115, 70, 670, 25, _tr("Name"));
+      db_entities_name->labelsize(16);
+      db_entities_name->textsize(16);
+      add_input_field_to_map("entities", "name", db_entities_name);
+    } // Fl_Input* db_entities_name
+    { db_entities_company = new Fl_Input(115, 100, 670, 25, _tr("Company"));
+      db_entities_company->labelsize(16);
+      db_entities_company->textsize(16);
+      add_input_field_to_map("entities", "company", db_entities_company);
+    } // Fl_Input* db_entities_company
+    { db_entities_address = new Fl_Input(115, 130, 670, 25, _tr("Address"));
+      db_entities_address->labelsize(16);
+      db_entities_address->textsize(16);
+      add_input_field_to_map("entities", "address", db_entities_address);
+    } // Fl_Input* db_entities_address
+    { db_entities_zip = new Fl_Input(115, 160, 95, 25, _tr("ZIP"));
+      db_entities_zip->labelsize(16);
+      db_entities_zip->textsize(16);
+      add_input_field_to_map("entities", "zip", db_entities_zip);
+    } // Fl_Input* db_entities_zip
+    { db_entities_city = new Fl_Input(311, 160, 474, 25, _tr("City"));
+      db_entities_city->labelsize(16);
+      db_entities_city->textsize(16);
+      add_input_field_to_map("entities", "city", db_entities_city);
+    } // Fl_Input* db_entities_city
+    { db_entities_state = new Fl_Input(115, 189, 390, 25, _tr("State"));
+      db_entities_state->labelsize(16);
+      db_entities_state->textsize(16);
+      add_input_field_to_map("entities", "state", db_entities_state);
+    } // Fl_Input* db_entities_state
+    { db_entities_country = new Fl_Input(585, 190, 200, 25, _tr("Country"));
+      db_entities_country->labelsize(16);
+      db_entities_country->textsize(16);
+      add_input_field_to_map("entities", "country", db_entities_country);
+    } // Fl_Input* db_entities_country
+    { db_entities_tax_number = new Fl_Input(115, 220, 200, 25, _tr("Tax Num."));
+      db_entities_tax_number->labelsize(16);
+      db_entities_tax_number->textsize(16);
+      add_input_field_to_map("entities", "tax_number", db_entities_tax_number);
+    } // Fl_Input* db_entities_tax_number
+    { db_entities_show_on_sales = new Fl_Check_Button(325, 220, 115, 25, _tr("Sales"));
+      db_entities_show_on_sales->down_box(FL_DOWN_BOX);
+      db_entities_show_on_sales->labelsize(16);
+      add_input_field_to_map("entities", "show_on_sales", db_entities_show_on_sales);
+    } // Fl_Check_Button* db_entities_show_on_sales
+    { db_entities_show_on_buys = new Fl_Check_Button(445, 220, 125, 25, _tr("Buys"));
+      db_entities_show_on_buys->down_box(FL_DOWN_BOX);
+      db_entities_show_on_buys->labelsize(16);
+      add_input_field_to_map("entities", "show_on_buys", db_entities_show_on_buys);
+    } // Fl_Check_Button* db_entities_show_on_buys
+    { db_entities_is_active = new Fl_Check_Button(585, 220, 155, 25, _tr("Active"));
+      db_entities_is_active->down_box(FL_DOWN_BOX);
+      db_entities_is_active->labelsize(16);
+      add_input_field_to_map("entities", "is_active", db_entities_is_active);
+    } // Fl_Check_Button* db_entities_is_active
+    { db_entities_phone = new Fl_Input(115, 249, 200, 25, _tr("Phone"));
+      db_entities_phone->labelsize(16);
+      db_entities_phone->textsize(16);
+      add_input_field_to_map("entities", "phone", db_entities_phone);
+    } // Fl_Input* db_entities_phone
+    { db_entities_fax = new Fl_Input(370, 249, 200, 25, _tr("Fax"));
+      db_entities_fax->labelsize(16);
+      db_entities_fax->textsize(16);
+      add_input_field_to_map("entities", "fax", db_entities_fax);
+    } // Fl_Input* db_entities_fax
+    { db_entities_use_sales_tax2 = new Fl_Check_Button(585, 250, 155, 25, _tr("Use Sales Tax II"));
+      db_entities_use_sales_tax2->down_box(FL_DOWN_BOX);
+      db_entities_use_sales_tax2->labelsize(16);
+      add_input_field_to_map("entities", "use_sales_tax2", db_entities_use_sales_tax2);
+    } // Fl_Check_Button* db_entities_use_sales_tax2
+    { db_entities_email = new Fl_Input(115, 280, 455, 25, _tr("Email"));
+      db_entities_email->labelsize(16);
+      db_entities_email->textsize(16);
+      add_input_field_to_map("entities", "email", db_entities_email);
+    } // Fl_Input* db_entities_email
+    { db_entities_sales_tax_exempt = new Fl_Check_Button(585, 280, 155, 25, _tr("Sales Tax Exempt"));
+      db_entities_sales_tax_exempt->down_box(FL_DOWN_BOX);
+      db_entities_sales_tax_exempt->labelsize(16);
+      add_input_field_to_map("entities", "sales_tax_exempt", db_entities_sales_tax_exempt);
+    } // Fl_Check_Button* db_entities_sales_tax_exempt
+    { db_entities_web = new Fl_Input(115, 310, 455, 25, _tr("Web"));
+      db_entities_web->labelsize(16);
+      db_entities_web->textsize(16);
+      add_input_field_to_map("entities", "web", db_entities_web);
+    } // Fl_Input* db_entities_web
+    { db_entities_irpf_pct_retention = new Fl_Float_Input_Fmt(585, 310, 60, 25, _tr("I.R.P.F. %"));
+      db_entities_irpf_pct_retention->type(1);
+      db_entities_irpf_pct_retention->box(FL_DOWN_BOX);
+      db_entities_irpf_pct_retention->color(FL_BACKGROUND2_COLOR);
+      db_entities_irpf_pct_retention->selection_color(FL_SELECTION_COLOR);
+      db_entities_irpf_pct_retention->labeltype(FL_NORMAL_LABEL);
+      db_entities_irpf_pct_retention->labelfont(0);
+      db_entities_irpf_pct_retention->labelsize(16);
+      db_entities_irpf_pct_retention->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_irpf_pct_retention->textsize(16);
+      db_entities_irpf_pct_retention->align(FL_ALIGN_RIGHT);
+      db_entities_irpf_pct_retention->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "irpf_pct_retention", db_entities_irpf_pct_retention);
+    } // Fl_Float_Input_Fmt* db_entities_irpf_pct_retention
+    { db_entities_contact = new Fl_Input(115, 340, 455, 25, _tr("Contact"));
+      db_entities_contact->labelsize(16);
+      db_entities_contact->textsize(16);
+      add_input_field_to_map("entities", "contact", db_entities_contact);
+    } // Fl_Input* db_entities_contact
+    { db_entities_gps_coordinates = new Fl_Input(630, 340, 155, 25, _tr("GPS"));
+      db_entities_gps_coordinates->labelsize(16);
+      db_entities_gps_coordinates->textsize(16);
+      add_input_field_to_map("entities", "gps_coordinates", db_entities_gps_coordinates);
+    } // Fl_Input* db_entities_gps_coordinates
+    { local o = new Fl_Group(675, 394, 110, 151);
+      { local o = new Fl_Box(675, 394, 110, 73, _tr("Spacer"));
+        o->labeltype(FL_NO_LABEL);
+        Fl_Group.current()->resizable(o);
+      } // Fl_Box* o
+      { 
+        btnDbAction = new My_Fl_Return_Button(675, 470, 110, 25, _tr("Action"));
+        btnDbAction->labelsize(16);
+      } // Fl_Button* btnDbAction
+      { 
+        dbAction = new Fl_Button(675, 520, 110, 25);
+        dbAction->label(_tr("Action"));
+        dbAction->down_box(FL_BORDER_BOX);
+        dbAction->labelsize(16);
+        dbAction->textsize(16);
+        dbAction->align(FL_ALIGN_TOP);
+      } // Fl_Choice* dbAction
+      o->end();
+    } // Fl_Group* o
+    { local o = new Fl_Tabs(15, 375, 650, 181);
+      o->selection_color(4);
+      o->labelsize(16);
+      o->labelcolor(FL_BACKGROUND2_COLOR);
+      { tabNotes = new Fl_Group(15, 405, 650, 150, _tr("Notes"));
+        tabNotes->labelsize(16);
+        { db_entities_notes = new Fl_Text_Editor_Buffered(15, 405, 650, 150);
+          db_entities_notes->type(4);
+          db_entities_notes->box(FL_DOWN_BOX);
+          db_entities_notes->color(FL_BACKGROUND2_COLOR);
+          db_entities_notes->selection_color(FL_SELECTION_COLOR);
+          db_entities_notes->labeltype(FL_NO_LABEL);
+          db_entities_notes->labelfont(0);
+          db_entities_notes->labelsize(16);
+          db_entities_notes->labelcolor(FL_FOREGROUND_COLOR);
+          db_entities_notes->textsize(16);
+          db_entities_notes->align(FL_ALIGN_TOP_LEFT);
+          db_entities_notes->when(FL_WHEN_RELEASE);
+          Fl_Group.current()->resizable(db_entities_notes);
+          add_input_field_to_map("entities", "notes", db_entities_notes);
+        } // Fl_Text_Editor_Buffered* db_entities_notes
+        tabNotes->end();
+      } // Fl_Group* tabNotes
+      { tabTags = new Fl_Group(15, 405, 650, 150, _tr("Tags"));
+        tabTags->labelsize(16);
+        tabTags->hide();
+        { db_entities_tags = new Fl_Text_Editor_Buffered(15, 405, 650, 150);
+          db_entities_tags->type(4);
+          db_entities_tags->box(FL_DOWN_BOX);
+          db_entities_tags->color(FL_BACKGROUND2_COLOR);
+          db_entities_tags->selection_color(FL_SELECTION_COLOR);
+          db_entities_tags->labeltype(FL_NO_LABEL);
+          db_entities_tags->labelfont(0);
+          db_entities_tags->labelsize(16);
+          db_entities_tags->labelcolor(FL_FOREGROUND_COLOR);
+          db_entities_tags->textsize(16);
+          db_entities_tags->align(FL_ALIGN_TOP_LEFT);
+          db_entities_tags->when(FL_WHEN_RELEASE);
+          Fl_Group.current()->resizable(db_entities_tags);
+          add_input_field_to_map("entities", "tags", db_entities_tags);
+        } // Fl_Text_Editor_Buffered* db_entities_tags
+        tabTags->end();
+      } // Fl_Group* tabTags
+      { tabGroups = new Fl_Group(15, 400, 650, 156, _tr("Groups"));
+        tabGroups->hide();
+        { db_entities_group_id = new Flu_Tree_Browser(15, 405, 650, 150);
+          db_entities_group_id->box(FL_DOWN_BOX);
+          db_entities_group_id->color(FL_BACKGROUND2_COLOR);
+          db_entities_group_id->selection_color(FL_SELECTION_COLOR);
+          db_entities_group_id->labeltype(FL_NORMAL_LABEL);
+          db_entities_group_id->labelfont(0);
+          db_entities_group_id->labelsize(16);
+          db_entities_group_id->labelcolor(FL_FOREGROUND_COLOR);
+          db_entities_group_id->align(FL_ALIGN_TOP);
+          db_entities_group_id->when(FL_WHEN_CHANGED);
+          add_input_field_to_map("entities", "group_id", db_entities_group_id);
+        } // Flu_Tree_Browser* db_entities_group_id
+        tabGroups->end();
+      } // Fl_Group* tabGroups
+      o->end();
+    } // Fl_Tabs* o
+    { local o = new Fl_Check_Button(375, 380, 102, 25, _tr("Wrap lines"));
+      o->down_box(FL_DOWN_BOX);
+      o->value(1);
+      o->labelsize(16);
+      //o->callback(cb_Wrap);
+    } // Fl_Check_Button* o
+    tabMain->end();
+    Fl_Group.current()->resizable(tabMain);
+  } // Fl_Group* tabMain
+  { tabTotals = new Fl_Group(5, 62, 790, 493, _tr("Totals"));
+    tabTotals->color(246);
+    tabTotals->labelsize(16);
+    tabTotals->hide();
+    { db_entities_credit_allowed = new Fl_Float_Input_Fmt(140, 75, 110, 25, _tr("Credit"));
+      db_entities_credit_allowed->type(1);
+      db_entities_credit_allowed->box(FL_DOWN_BOX);
+      db_entities_credit_allowed->color(FL_BACKGROUND2_COLOR);
+      db_entities_credit_allowed->selection_color(FL_SELECTION_COLOR);
+      db_entities_credit_allowed->labeltype(FL_NORMAL_LABEL);
+      db_entities_credit_allowed->labelfont(0);
+      db_entities_credit_allowed->labelsize(16);
+      db_entities_credit_allowed->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_credit_allowed->textsize(16);
+      db_entities_credit_allowed->align(FL_ALIGN_LEFT);
+      db_entities_credit_allowed->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "credit_allowed", db_entities_credit_allowed);
+    } // Fl_Float_Input_Fmt* db_entities_credit_allowed
+    { db_entities_balance = new Fl_Float_Input_Fmt(140, 110, 110, 25, _tr("Balance"));
+      db_entities_balance->type(1);
+      db_entities_balance->box(FL_DOWN_BOX);
+      db_entities_balance->color(FL_BACKGROUND2_COLOR);
+      db_entities_balance->selection_color(FL_SELECTION_COLOR);
+      db_entities_balance->labeltype(FL_NORMAL_LABEL);
+      db_entities_balance->labelfont(0);
+      db_entities_balance->labelsize(16);
+      db_entities_balance->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_balance->textsize(16);
+      db_entities_balance->align(FL_ALIGN_LEFT);
+      db_entities_balance->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "balance", db_entities_balance);
+    } // Fl_Float_Input_Fmt* db_entities_balance
+    { db_entities_sales_quoted = new Fl_Float_Input_Fmt(140, 155, 110, 25, _tr("Sales Quoted"));
+      db_entities_sales_quoted->type(1);
+      db_entities_sales_quoted->box(FL_DOWN_BOX);
+      db_entities_sales_quoted->color(FL_BACKGROUND2_COLOR);
+      db_entities_sales_quoted->selection_color(FL_SELECTION_COLOR);
+      db_entities_sales_quoted->labeltype(FL_NORMAL_LABEL);
+      db_entities_sales_quoted->labelfont(0);
+      db_entities_sales_quoted->labelsize(16);
+      db_entities_sales_quoted->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_sales_quoted->textsize(16);
+      db_entities_sales_quoted->align(FL_ALIGN_LEFT);
+      db_entities_sales_quoted->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "sales_quoted", db_entities_sales_quoted);
+    } // Fl_Float_Input_Fmt* db_entities_sales_quoted
+    { db_entities_sales_ordered = new Fl_Float_Input_Fmt(140, 190, 110, 25, _tr("Sales Ordered"));
+      db_entities_sales_ordered->type(1);
+      db_entities_sales_ordered->box(FL_DOWN_BOX);
+      db_entities_sales_ordered->color(FL_BACKGROUND2_COLOR);
+      db_entities_sales_ordered->selection_color(FL_SELECTION_COLOR);
+      db_entities_sales_ordered->labeltype(FL_NORMAL_LABEL);
+      db_entities_sales_ordered->labelfont(0);
+      db_entities_sales_ordered->labelsize(16);
+      db_entities_sales_ordered->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_sales_ordered->textsize(16);
+      db_entities_sales_ordered->align(FL_ALIGN_LEFT);
+      db_entities_sales_ordered->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "sales_ordered", db_entities_sales_ordered);
+    } // Fl_Float_Input_Fmt* db_entities_sales_ordered
+    { db_entities_sales_delivered = new Fl_Float_Input_Fmt(140, 225, 110, 25, _tr("Sales Delivered"));
+      db_entities_sales_delivered->type(1);
+      db_entities_sales_delivered->box(FL_DOWN_BOX);
+      db_entities_sales_delivered->color(FL_BACKGROUND2_COLOR);
+      db_entities_sales_delivered->selection_color(FL_SELECTION_COLOR);
+      db_entities_sales_delivered->labeltype(FL_NORMAL_LABEL);
+      db_entities_sales_delivered->labelfont(0);
+      db_entities_sales_delivered->labelsize(16);
+      db_entities_sales_delivered->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_sales_delivered->textsize(16);
+      db_entities_sales_delivered->align(FL_ALIGN_LEFT);
+      db_entities_sales_delivered->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "sales_delivered", db_entities_sales_delivered);
+    } // Fl_Float_Input_Fmt* db_entities_sales_delivered
+    { db_entities_sales_invoiced = new Fl_Float_Input_Fmt(140, 260, 110, 25, _tr("Sales Invoiced"));
+      db_entities_sales_invoiced->type(1);
+      db_entities_sales_invoiced->box(FL_DOWN_BOX);
+      db_entities_sales_invoiced->color(FL_BACKGROUND2_COLOR);
+      db_entities_sales_invoiced->selection_color(FL_SELECTION_COLOR);
+      db_entities_sales_invoiced->labeltype(FL_NORMAL_LABEL);
+      db_entities_sales_invoiced->labelfont(0);
+      db_entities_sales_invoiced->labelsize(16);
+      db_entities_sales_invoiced->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_sales_invoiced->textsize(16);
+      db_entities_sales_invoiced->align(FL_ALIGN_LEFT);
+      db_entities_sales_invoiced->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "sales_invoiced", db_entities_sales_invoiced);
+    } // Fl_Float_Input_Fmt* db_entities_sales_invoiced
+    { db_entities_sales_discount = new Fl_Float_Input_Fmt(140, 295, 110, 25, _tr("Sales Discount"));
+      db_entities_sales_discount->type(1);
+      db_entities_sales_discount->box(FL_DOWN_BOX);
+      db_entities_sales_discount->color(FL_BACKGROUND2_COLOR);
+      db_entities_sales_discount->selection_color(FL_SELECTION_COLOR);
+      db_entities_sales_discount->labeltype(FL_NORMAL_LABEL);
+      db_entities_sales_discount->labelfont(0);
+      db_entities_sales_discount->labelsize(16);
+      db_entities_sales_discount->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_sales_discount->textsize(16);
+      db_entities_sales_discount->align(FL_ALIGN_LEFT);
+      db_entities_sales_discount->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "sales_discount", db_entities_sales_discount);
+    } // Fl_Float_Input_Fmt* db_entities_sales_discount
+    { db_entities_sales_paid = new Fl_Float_Input_Fmt(140, 330, 110, 25, _tr("Sales Paid"));
+      db_entities_sales_paid->type(1);
+      db_entities_sales_paid->box(FL_DOWN_BOX);
+      db_entities_sales_paid->color(FL_BACKGROUND2_COLOR);
+      db_entities_sales_paid->selection_color(FL_SELECTION_COLOR);
+      db_entities_sales_paid->labeltype(FL_NORMAL_LABEL);
+      db_entities_sales_paid->labelfont(0);
+      db_entities_sales_paid->labelsize(16);
+      db_entities_sales_paid->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_sales_paid->textsize(16);
+      db_entities_sales_paid->align(FL_ALIGN_LEFT);
+      db_entities_sales_paid->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "sales_paid", db_entities_sales_paid);
+    } // Fl_Float_Input_Fmt* db_entities_sales_paid
+    { db_entities_buys_quoted = new Fl_Float_Input_Fmt(410, 155, 110, 25, _tr("Buys Quoted"));
+      db_entities_buys_quoted->type(1);
+      db_entities_buys_quoted->box(FL_DOWN_BOX);
+      db_entities_buys_quoted->color(FL_BACKGROUND2_COLOR);
+      db_entities_buys_quoted->selection_color(FL_SELECTION_COLOR);
+      db_entities_buys_quoted->labeltype(FL_NORMAL_LABEL);
+      db_entities_buys_quoted->labelfont(0);
+      db_entities_buys_quoted->labelsize(16);
+      db_entities_buys_quoted->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_buys_quoted->textsize(16);
+      db_entities_buys_quoted->align(FL_ALIGN_LEFT);
+      db_entities_buys_quoted->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "buys_quoted", db_entities_buys_quoted);
+    } // Fl_Float_Input_Fmt* db_entities_buys_quoted
+    { db_entities_buys_ordered = new Fl_Float_Input_Fmt(410, 190, 110, 25, _tr("Buys Ordered"));
+      db_entities_buys_ordered->type(1);
+      db_entities_buys_ordered->box(FL_DOWN_BOX);
+      db_entities_buys_ordered->color(FL_BACKGROUND2_COLOR);
+      db_entities_buys_ordered->selection_color(FL_SELECTION_COLOR);
+      db_entities_buys_ordered->labeltype(FL_NORMAL_LABEL);
+      db_entities_buys_ordered->labelfont(0);
+      db_entities_buys_ordered->labelsize(16);
+      db_entities_buys_ordered->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_buys_ordered->textsize(16);
+      db_entities_buys_ordered->align(FL_ALIGN_LEFT);
+      db_entities_buys_ordered->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "buys_ordered", db_entities_buys_ordered);
+    } // Fl_Float_Input_Fmt* db_entities_buys_ordered
+    { db_entities_buys_received = new Fl_Float_Input_Fmt(410, 225, 110, 25, _tr("Buys Received"));
+      db_entities_buys_received->type(1);
+      db_entities_buys_received->box(FL_DOWN_BOX);
+      db_entities_buys_received->color(FL_BACKGROUND2_COLOR);
+      db_entities_buys_received->selection_color(FL_SELECTION_COLOR);
+      db_entities_buys_received->labeltype(FL_NORMAL_LABEL);
+      db_entities_buys_received->labelfont(0);
+      db_entities_buys_received->labelsize(16);
+      db_entities_buys_received->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_buys_received->textsize(16);
+      db_entities_buys_received->align(FL_ALIGN_LEFT);
+      db_entities_buys_received->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "buys_received", db_entities_buys_received);
+    } // Fl_Float_Input_Fmt* db_entities_buys_received
+    { db_entities_buys_invoiced = new Fl_Float_Input_Fmt(410, 260, 110, 25, _tr("Buys Invoiced"));
+      db_entities_buys_invoiced->type(1);
+      db_entities_buys_invoiced->box(FL_DOWN_BOX);
+      db_entities_buys_invoiced->color(FL_BACKGROUND2_COLOR);
+      db_entities_buys_invoiced->selection_color(FL_SELECTION_COLOR);
+      db_entities_buys_invoiced->labeltype(FL_NORMAL_LABEL);
+      db_entities_buys_invoiced->labelfont(0);
+      db_entities_buys_invoiced->labelsize(16);
+      db_entities_buys_invoiced->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_buys_invoiced->textsize(16);
+      db_entities_buys_invoiced->align(FL_ALIGN_LEFT);
+      db_entities_buys_invoiced->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "buys_invoiced", db_entities_buys_invoiced);
+    } // Fl_Float_Input_Fmt* db_entities_buys_invoiced
+    { db_entities_buys_paid = new Fl_Float_Input_Fmt(410, 330, 110, 25, _tr("Buys Paid"));
+      db_entities_buys_paid->type(1);
+      db_entities_buys_paid->box(FL_DOWN_BOX);
+      db_entities_buys_paid->color(FL_BACKGROUND2_COLOR);
+      db_entities_buys_paid->selection_color(FL_SELECTION_COLOR);
+      db_entities_buys_paid->labeltype(FL_NORMAL_LABEL);
+      db_entities_buys_paid->labelfont(0);
+      db_entities_buys_paid->labelsize(16);
+      db_entities_buys_paid->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_buys_paid->textsize(16);
+      db_entities_buys_paid->align(FL_ALIGN_LEFT);
+      db_entities_buys_paid->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "buys_paid", db_entities_buys_paid);
+    } // Fl_Float_Input_Fmt* db_entities_buys_paid
+    { db_entities_buys_discount = new Fl_Float_Input_Fmt(410, 295, 110, 25, _tr("Buys Discount"));
+      db_entities_buys_discount->type(1);
+      db_entities_buys_discount->box(FL_DOWN_BOX);
+      db_entities_buys_discount->color(FL_BACKGROUND2_COLOR);
+      db_entities_buys_discount->selection_color(FL_SELECTION_COLOR);
+      db_entities_buys_discount->labeltype(FL_NORMAL_LABEL);
+      db_entities_buys_discount->labelfont(0);
+      db_entities_buys_discount->labelsize(16);
+      db_entities_buys_discount->labelcolor(FL_FOREGROUND_COLOR);
+      db_entities_buys_discount->textsize(16);
+      db_entities_buys_discount->align(FL_ALIGN_LEFT);
+      db_entities_buys_discount->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("entities", "buys_discount", db_entities_buys_discount);
+    } // Fl_Float_Input_Fmt* db_entities_buys_discount
+    tabTotals->end();
+  } // Fl_Group* tabTotals
+  { tabChartStatistics = new Fl_Group(5, 62, 790, 493, _tr("Statistics"));
+    tabChartStatistics->color(246);
+    tabChartStatistics->labelsize(16);
+    tabChartStatistics->hide();
+    tabChartStatistics->end();
+  } // Fl_Group* tabChartStatistics
+  { tabHistory = new Fl_Group(5, 59, 790, 496, _tr("History"));
+    tabHistory->color(246);
+    tabHistory->labelsize(16);
+    tabHistory->hide();
+    tabHistory->end();
+  } // Fl_Group* tabHistory
+  { tabReports = new Fl_Group(5, 59, 790, 496, _tr("Reports"));
+    tabReports->color(246);
+    tabReports->labelsize(16);
+    tabReports->hide();
+    { btnEntitesListContactReport = new Fl_Button(255, 100, 215, 25, _tr("Entities List Contact Report"));
+    } // Fl_Button* btnEntitesListContactReport
+    { print_progress = new Fl_Progress(255, 140, 215, 25, _tr("Printing Progress"));
+    } // Fl_Progress* print_progress
+    tabReports->end();
+  } // Fl_Group* tabReports
+  tabs->end();
+  Fl_Group.current()->resizable(tabs);
+} // Fl_Tabs* tabs
+end();
+}
+	
+}

+ 1326 - 0
ourbiz/edit-order-window.nut

@@ -0,0 +1,1326 @@
+class Fl_Box_ClearLabel extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Flu_Combo_List extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Choice_Int extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Float_Input_Fmt extends Fl_Float_Input {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class My_Fl_Float_Input extends Fl_Float_Input {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+class My_Fl_Return_Button extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Choice_Str extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+
+function add_input_field_to_map(tbl, fldname, fld){
+}
+	
+//class EditOrderWindow extends Fl_Group {
+class EditOrderWindow extends MyBaseWindow {
+	delivery_calc_window = 0;
+	entities_list_window = 0;
+	products_list_window = 0;
+	calendar_window = 0;
+	db_orders_mdate=null;
+	pack_line2=null;
+	db_orders_series=null;
+	db_orders_order_number=null;
+	db_orders_entity_id=null;
+	db_orders_entity_name=null;
+	btnSearchEntity=null;
+	db_orders_entity_order_number=null;
+	tabs=null;
+	tabMain=null;
+	pack_line3=null;
+	out_lines=null;
+	db_orders_weight_total=null;
+	btnCalcDelivery=null;
+	db_orders_payment_type_id=null;
+	btnSortLines=null;
+	db_orders_order_date=null;
+	btnShowCalendar=null;
+	group_totals=null;
+	db_orders_discount_amt=null;
+	db_orders_subtotal_amt=null;
+	db_orders_sales_tax1_amt=null;
+	db_orders_sales_tax2_amt=null;
+	db_orders_irpf_amt=null;
+	db_orders_total_amt=null;
+	db_orders_cash=null;
+	cash_return=null;
+	linesTab=null;
+	group_lines=null;
+	db_orders_lines_batch_order_line_quantity=null;
+	db_orders_lines_batch_order_line_id=null;
+	btnSearchBatchOrderLineId=null;
+	db_orders_lines_xref_order_line_quantity=null;
+	db_orders_lines_xref_order_line_id=null;
+	btnSearchXrefOrderLineId=null;
+	db_orders_lines_product_id=null;
+	db_orders_lines_description=null;
+	btnSearchProduct=null;
+	db_orders_lines_price_decimals=null;
+	db_orders_lines_first_total=null;
+	db_orders_lines_discount_amt=null;
+	db_orders_lines_line_subtotal=null;
+	db_orders_lines_sales_tax2_pct=null;
+	db_orders_lines_sales_tax1_pct=null;
+	db_orders_lines_sales_tax1_amt=null;
+	db_orders_lines_line_total=null;
+	tabLineNotes=null;
+	db_orders_lines_notes=null;
+	tabDues=null;
+	grid_dues=null;
+	due_id=null;
+	due_date=null;
+	btnShowCalendarDueDate=null;
+	due_pct=null;
+	due_amount=null;
+	tabPayments=null;
+	grid_payments=null;
+	payment_id=null;
+	payment_date=null;
+	btnShowCalendarPaymentDate=null;
+	payemnt_amount=null;
+	tabDelivery=null;
+	db_orders_entity_address=null;
+	db_orders_entity_zip=null;
+	db_orders_entity_city=null;
+	db_orders_entity_state=null;
+	db_orders_entity_country=null;
+	db_orders_entity_phone=null;
+	db_orders_entity_tax_number=null;
+	db_orders_order_valid_till_date=null;
+	btnShowCalendarValidTill=null;
+	db_orders_entity_use_sales_tax2=null;
+	db_orders_entity_sales_tax_exempt=null;
+	db_orders_notes=null;
+	db_orders_irpf_pct_retention=null;
+	tabOptions=null;
+	opt_ask_for_printer=null;
+	opt_print_only_data=null;
+	opt_print_to_pdf=null;
+	opt_print_page_format=null;
+	btnOptPrint=null;
+	opt_email_program=null;
+	opt_email_program_command=null;
+	btnOptSendEmail=null;
+	opt_print_order_company_info=null;
+	opt_print_order_bottom_info=null;
+	tabChartStatistics=null;
+	tabHistory=null;
+	tabPrintPreview=null;
+	tabTotals=null;
+	totals_balance=null;
+	db_totals_overview_sales_quoted=null;
+	db_totals_overview_sales_ordered=null;
+	db_totals_overview_sales_delivered=null;
+	db_totals_overview_sales_invoiced=null;
+	db_totals_overview_sales_discount=null;
+	db_totals_overview_sales_tax1=null;
+	db_totals_overview_sales_tax2=null;
+	db_totals_overview_sales_paid=null;
+	db_totals_overview_buys_quoted=null;
+	db_totals_overview_buys_ordered=null;
+	db_totals_overview_buys_received=null;
+	db_totals_overview_buys_invoiced=null;
+	db_totals_overview_buys_discount=null;
+	db_totals_overview_buys_tax1=null;
+	db_totals_overview_buys_tax2=null;
+	db_totals_overview_buys_paid=null;
+	db_orders_order_type_id=null;
+	grid_lines=null;
+	btnPrint=null;
+	db_orders_lines_quantity=null;
+	db_orders_lines_price=null;
+	db_orders_lines_weight=null;
+	db_orders_lines_discount_pct=null;
+	btnSaveLine=null;
+	btnDueSave=null;
+	btnPaymentSave=null;
+	btnNumberOrder=null;
+	dbAction=null;
+	btnDbAction=null;
+	btnRefreshTotals=null;
+	
+constructor() {
+	base.constructor(10, 50, 800, 560, _tr("Edit Order"));
+begin();
+this->box(FL_FLAT_BOX);
+this->color(FL_BACKGROUND_COLOR);
+this->selection_color(FL_BACKGROUND_COLOR);
+this->labeltype(FL_NO_LABEL);
+this->labelfont(0);
+this->labelsize(16);
+this->labelcolor(FL_FOREGROUND_COLOR);
+this->align((FL_ALIGN_TOP));
+this->when(FL_WHEN_RELEASE);
+delivery_calc_window = 0;
+entities_list_window = 0;
+products_list_window = 0;
+calendar_window = 0;
+{ local o = new Fl_Group(5, 1, 792, 62);
+  { db_orders_mdate = new Fl_Output(670, 5, 125, 25);
+    db_orders_mdate->labeltype(FL_NO_LABEL);
+    db_orders_mdate->labelsize(16);
+    db_orders_mdate->textsize(16);
+    add_input_field_to_map("orders", "mdate", db_orders_mdate);
+  } // Fl_Output* db_orders_mdate
+  { db_orders_order_type_id = new Flu_Combo_List(5, 5, 655, 25);
+    db_orders_order_type_id->tooltip(_tr("Selection of the order type"));
+    db_orders_order_type_id->box(FL_DOWN_BOX);
+    db_orders_order_type_id->color(FL_BACKGROUND_COLOR);
+    db_orders_order_type_id->selection_color(FL_BACKGROUND_COLOR);
+    db_orders_order_type_id->labeltype(FL_NO_LABEL);
+    db_orders_order_type_id->labelfont(1);
+    db_orders_order_type_id->labelsize(16);
+    db_orders_order_type_id->labelcolor(FL_FOREGROUND_COLOR);
+    db_orders_order_type_id->align((FL_ALIGN_CENTER));
+    db_orders_order_type_id->when(FL_WHEN_RELEASE);
+    add_input_field_to_map("orders", "order_type_id", db_orders_order_type_id);
+  } // Flu_Combo_List* db_orders_order_type_id
+  { local o = pack_line2 = new Fl_Pack(5, 35, 790, 25);
+    pack_line2->type(1);
+    pack_line2->labelsize(16);
+    { db_orders_series = new Fl_Input(55, 35, 45, 25, _tr("Series"));
+      db_orders_series->labelsize(16);
+      db_orders_series->textsize(16);
+      add_input_field_to_map("orders", "series", db_orders_series);
+    } // Fl_Input* db_orders_series
+    { local o = db_orders_order_number = new Fl_Int_Input(172, 35, 95, 25, _tr("Number"));
+      db_orders_order_number->type(2);
+      db_orders_order_number->labelsize(16);
+      db_orders_order_number->textsize(16);
+      add_input_field_to_map("orders", "order_number", db_orders_order_number);
+      o->use_numeric_format(0);
+    } // Fl_Int_Input* db_orders_order_number
+    { db_orders_entity_id = new Fl_Int_Input(319, 35, 95, 25, _tr("Entity"));
+      db_orders_entity_id->type(2);
+      db_orders_entity_id->labelsize(16);
+      db_orders_entity_id->textsize(16);
+      add_input_field_to_map("orders", "entity_id", db_orders_entity_id);
+    } // Fl_Int_Input* db_orders_entity_id
+    { db_orders_entity_name = new Fl_Input(420, 35, 335, 25);
+      db_orders_entity_name->tooltip(_tr("Type partal description to search on availlable entities"));
+      db_orders_entity_name->labeltype(FL_NO_LABEL);
+      db_orders_entity_name->labelsize(16);
+      db_orders_entity_name->textfont(1);
+      db_orders_entity_name->textsize(16);
+      Fl_Group.current()->resizable(db_orders_entity_name);
+      add_input_field_to_map("orders", "entity_name", db_orders_entity_name);
+    } // Fl_Input* db_orders_entity_name
+    { btnSearchEntity = new Fl_Button(765, 35, 30, 25, _tr("@<->"));
+      btnSearchEntity->tooltip(_tr("Show entities search window"));
+      btnSearchEntity->labelsize(18);
+      btnSearchEntity->labelcolor(22);
+    } // Fl_Button* btnSearchEntity
+    o->spacing(5);
+    o->with_label(1);
+    pack_line2->end();
+  } // Fl_Pack* pack_line2
+  o->end();
+} // Fl_Group* o
+{ db_orders_entity_order_number = new Fl_Input(585, 65, 210, 25, _tr("Their Nº"));
+  db_orders_entity_order_number->labelsize(16);
+  db_orders_entity_order_number->textsize(16);
+  add_input_field_to_map("orders", "entity_order_number", db_orders_entity_order_number);
+} // Fl_Input* db_orders_entity_order_number
+{ tabs = new Fl_Tabs(5, 68, 790, 487);
+  tabs->selection_color(4);
+  tabs->labelsize(16);
+  tabs->labelcolor(FL_BACKGROUND2_COLOR);
+  { tabMain = new Fl_Group(5, 95, 790, 460, _tr("Main"));
+    tabMain->color(246);
+    tabMain->labelfont(2);
+    tabMain->labelsize(16);
+    { local o = pack_line3 = new Fl_Pack(11, 105, 780, 25);
+      pack_line3->type(1);
+      pack_line3->labelsize(16);
+      { local o = out_lines = new Fl_Output(57, 105, 69, 25, _tr("Lines"));
+        out_lines->labelsize(16);
+        out_lines->textsize(16);
+        o->right_to_left(1);
+      } // Fl_Output* out_lines
+      { local o = db_orders_weight_total = new Fl_Output(189, 105, 110, 25, _tr("Weight"));
+        db_orders_weight_total->labelsize(16);
+        db_orders_weight_total->textsize(16);
+        o->right_to_left(1);
+        o->decimal_places(-2);
+        o->use_numeric_format(1);
+      } // Fl_Output* db_orders_weight_total
+      { btnCalcDelivery = new Fl_Button(309, 105, 30, 25, _tr("@<->"));
+        btnCalcDelivery->tooltip(_tr("Show delivery calc window"));
+        btnCalcDelivery->labelsize(18);
+        btnCalcDelivery->labelcolor(22);
+      } // Fl_Button* btnCalcDelivery
+      { db_orders_payment_type_id = new Fl_Choice_Int(345, 105, 235, 25);
+        db_orders_payment_type_id->box(FL_FLAT_BOX);
+        db_orders_payment_type_id->down_box(FL_BORDER_BOX);
+        db_orders_payment_type_id->color(FL_BACKGROUND_COLOR);
+        db_orders_payment_type_id->selection_color(FL_SELECTION_COLOR);
+        db_orders_payment_type_id->labeltype(FL_NO_LABEL);
+        db_orders_payment_type_id->labelfont(0);
+        db_orders_payment_type_id->labelsize(16);
+        db_orders_payment_type_id->labelcolor(FL_FOREGROUND_COLOR);
+        db_orders_payment_type_id->textfont(1);
+        db_orders_payment_type_id->textsize(16);
+        db_orders_payment_type_id->align((FL_ALIGN_LEFT));
+        db_orders_payment_type_id->when(FL_WHEN_RELEASE);
+        Fl_Group.current()->resizable(db_orders_payment_type_id);
+        add_input_field_to_map("orders", "payment_type_id", db_orders_payment_type_id);
+      } // Fl_Choice_Int* db_orders_payment_type_id
+      { btnSortLines = new Fl_Button(590, 105, 30, 25, _tr("@2"));
+        btnSortLines->tooltip(_tr("Sort lines by description"));
+        btnSortLines->labelsize(18);
+        btnSortLines->labelcolor(22);
+      } // Fl_Button* btnSortLines
+      { db_orders_order_date = new Fl_Input(629, 105, 120, 25);
+        db_orders_order_date->labeltype(FL_NO_LABEL);
+        db_orders_order_date->labelsize(16);
+        db_orders_order_date->textfont(1);
+        db_orders_order_date->textsize(16);
+        add_input_field_to_map("orders", "order_date", db_orders_order_date);
+      } // Fl_Input* db_orders_order_date
+      { btnShowCalendar = new Fl_Button(760, 105, 30, 25, _tr("@<->"));
+        btnShowCalendar->tooltip(_tr("Show calendar"));
+        btnShowCalendar->labelsize(18);
+        btnShowCalendar->labelcolor(22);
+      } // Fl_Button* btnShowCalendar
+      o->spacing(5);
+      o->with_label(1);
+      pack_line3->end();
+    } // Fl_Pack* pack_line3
+    { grid_lines = new Fl_Data_Table(10, 135, 780, 150);
+      grid_lines->resize(10, 135, 780, 150);
+      grid_lines->box(FL_NO_BOX);
+      grid_lines->color(FL_BACKGROUND2_COLOR);
+      grid_lines->selection_color(FL_SELECTION_COLOR);
+      grid_lines->labeltype(FL_NORMAL_LABEL);
+      grid_lines->labelfont(0);
+      grid_lines->labelsize(16);
+      grid_lines->labelcolor(FL_FOREGROUND_COLOR);
+      grid_lines->textsize(16);
+      grid_lines->align((FL_ALIGN_BOTTOM));
+      grid_lines->when(FL_WHEN_RELEASE_ALWAYS);
+      Fl_Group.current()->resizable(grid_lines);
+    } // Fl_Data_Table* grid_lines
+    { local o = new Fl_Group(10, 290, 781, 260);
+      { group_totals = new Fl_Group(600, 291, 190, 259);
+        group_totals->box(FL_UP_BOX);
+        group_totals->color(174);
+        { local o = db_orders_discount_amt = new Fl_Output(685, 297, 100, 25, _tr("Discount"));
+          db_orders_discount_amt->labelsize(16);
+          db_orders_discount_amt->textsize(16);
+          o->right_to_left(1);
+          o->use_numeric_format(1);
+          add_input_field_to_map("orders", "discount_amt", db_orders_discount_amt);
+        } // Fl_Output* db_orders_discount_amt
+        { local o = db_orders_subtotal_amt = new Fl_Output(684, 326, 100, 25, _tr("Subtotal"));
+          db_orders_subtotal_amt->labelsize(16);
+          db_orders_subtotal_amt->textsize(16);
+          o->right_to_left(1);
+          o->use_numeric_format(1);
+          add_input_field_to_map("orders", "subtotal_amt", db_orders_subtotal_amt);
+        } // Fl_Output* db_orders_subtotal_amt
+        { local o = db_orders_sales_tax1_amt = new Fl_Output(685, 356, 100, 25, _tr("V.A.T."));
+          db_orders_sales_tax1_amt->labelsize(16);
+          db_orders_sales_tax1_amt->textsize(16);
+          o->right_to_left(1);
+          o->use_numeric_format(1);
+          add_input_field_to_map("orders", "sales_tax1_amt", db_orders_sales_tax1_amt);
+        } // Fl_Output* db_orders_sales_tax1_amt
+        { local o = db_orders_sales_tax2_amt = new Fl_Output(684, 386, 100, 25, _tr("R.E."));
+          db_orders_sales_tax2_amt->labelsize(16);
+          db_orders_sales_tax2_amt->textsize(16);
+          o->right_to_left(1);
+          o->use_numeric_format(1);
+          add_input_field_to_map("orders", "sales_tax2_amt", db_orders_sales_tax2_amt);
+        } // Fl_Output* db_orders_sales_tax2_amt
+        { local o = db_orders_irpf_amt = new Fl_Output(685, 416, 100, 25, _tr("I.R.P.F."));
+          db_orders_irpf_amt->labelsize(16);
+          db_orders_irpf_amt->textsize(16);
+          o->right_to_left(1);
+          o->use_numeric_format(1);
+          add_input_field_to_map("orders", "irpf_amt", db_orders_irpf_amt);
+        } // Fl_Output* db_orders_irpf_amt
+        { local o = db_orders_total_amt = new Fl_Output(610, 453, 174, 33, _tr("Total"));
+          db_orders_total_amt->color(119);
+          db_orders_total_amt->labelfont(1);
+          db_orders_total_amt->textfont(1);
+          db_orders_total_amt->textsize(30);
+          db_orders_total_amt->align((FL_ALIGN_TOP_LEFT));
+          o->right_to_left(1);
+          o->use_numeric_format(1);
+          add_input_field_to_map("orders", "total_amt", db_orders_total_amt);
+        } // Fl_Output* db_orders_total_amt
+        { db_orders_cash = new Fl_Float_Input_Fmt(685, 490, 100, 25, _tr("Cash"));
+          db_orders_cash->type(1);
+          db_orders_cash->box(FL_DOWN_BOX);
+          db_orders_cash->color(FL_BACKGROUND2_COLOR);
+          db_orders_cash->selection_color(FL_SELECTION_COLOR);
+          db_orders_cash->labeltype(FL_NORMAL_LABEL);
+          db_orders_cash->labelfont(1);
+          db_orders_cash->labelsize(16);
+          db_orders_cash->labelcolor(FL_FOREGROUND_COLOR);
+          db_orders_cash->textfont(1);
+          db_orders_cash->textsize(16);
+          db_orders_cash->align((FL_ALIGN_LEFT));
+          db_orders_cash->when(FL_WHEN_RELEASE);
+          add_input_field_to_map("orders", "cash", db_orders_cash);
+        } // Fl_Float_Input_Fmt* db_orders_cash
+        { local o = cash_return = new Fl_Output(685, 520, 100, 25, _tr("Return"));
+          cash_return->labelfont(1);
+          cash_return->labelsize(16);
+          cash_return->textfont(1);
+          cash_return->textsize(16);
+          o->right_to_left(1);
+          o->use_numeric_format(1);
+        } // Fl_Output* cash_return
+        group_totals->end();
+      } // Fl_Group* group_totals
+      { btnPrint = new My_Fl_Return_Button(485, 525, 100, 25, _tr("Print"));
+        btnPrint->box(FL_UP_BOX);
+        btnPrint->color(FL_BACKGROUND_COLOR);
+        btnPrint->selection_color(FL_BACKGROUND_COLOR);
+        btnPrint->labeltype(FL_NORMAL_LABEL);
+        btnPrint->labelfont(0);
+        btnPrint->labelsize(16);
+        btnPrint->labelcolor(FL_FOREGROUND_COLOR);
+        btnPrint->align((FL_ALIGN_CENTER));
+        btnPrint->when(FL_WHEN_RELEASE);
+      } // My_Fl_Return_Button* btnPrint
+      { linesTab = new Fl_Tabs(10, 290, 585, 230);
+        linesTab->selection_color(4);
+        linesTab->labelfont(2);
+        linesTab->labelsize(16);
+        linesTab->labelcolor(FL_BACKGROUND2_COLOR);
+        { group_lines = new Fl_Group(10, 321, 585, 199, _tr("Line Edit"));
+          group_lines->box(FL_UP_BOX);
+          group_lines->color(166);
+          group_lines->labelfont(2);
+          group_lines->labelsize(16);
+          { local o = db_orders_lines_batch_order_line_quantity = new Fl_Output(265, 330, 110, 25, _tr("Batch Qty."));
+            db_orders_lines_batch_order_line_quantity->labelsize(16);
+            db_orders_lines_batch_order_line_quantity->textsize(16);
+            o->right_to_left(1);
+            add_input_field_to_map("orders_lines", "batch_order_line_quantity", db_orders_lines_batch_order_line_quantity);
+          } // Fl_Output* db_orders_lines_batch_order_line_quantity
+          { db_orders_lines_batch_order_line_id = new Fl_Int_Input(435, 329, 110, 25, _tr("Batch #"));
+            db_orders_lines_batch_order_line_id->type(2);
+            db_orders_lines_batch_order_line_id->labelsize(16);
+            db_orders_lines_batch_order_line_id->textsize(16);
+            add_input_field_to_map("orders_lines", "batch_order_line_id", db_orders_lines_batch_order_line_id);
+          } // Fl_Int_Input* db_orders_lines_batch_order_line_id
+          { btnSearchBatchOrderLineId = new Fl_Button(555, 329, 30, 25, _tr("@<->"));
+            btnSearchBatchOrderLineId->tooltip(_tr("Show products search window"));
+            btnSearchBatchOrderLineId->labelsize(18);
+            btnSearchBatchOrderLineId->labelcolor(22);
+          } // Fl_Button* btnSearchBatchOrderLineId
+          { local o = db_orders_lines_xref_order_line_quantity = new Fl_Output(265, 360, 110, 25, _tr("XRef. Qty."));
+            db_orders_lines_xref_order_line_quantity->labelsize(16);
+            db_orders_lines_xref_order_line_quantity->textsize(16);
+            o->right_to_left(1);
+            add_input_field_to_map("orders_lines", "xref_order_line_quantity", db_orders_lines_xref_order_line_quantity);
+          } // Fl_Output* db_orders_lines_xref_order_line_quantity
+          { db_orders_lines_xref_order_line_id = new Fl_Int_Input(435, 359, 110, 25, _tr("XRef #"));
+            db_orders_lines_xref_order_line_id->type(2);
+            db_orders_lines_xref_order_line_id->labelsize(16);
+            db_orders_lines_xref_order_line_id->textsize(16);
+            add_input_field_to_map("orders_lines", "xref_order_line_id", db_orders_lines_xref_order_line_id);
+          } // Fl_Int_Input* db_orders_lines_xref_order_line_id
+          { btnSearchXrefOrderLineId = new Fl_Button(555, 359, 30, 25, _tr("@<->"));
+            btnSearchXrefOrderLineId->tooltip(_tr("Show products search window"));
+            btnSearchXrefOrderLineId->labelsize(18);
+            btnSearchXrefOrderLineId->labelcolor(22);
+          } // Fl_Button* btnSearchXrefOrderLineId
+          { db_orders_lines_product_id = new Fl_Int_Input(21, 387, 70, 25, _tr("Code"));
+            db_orders_lines_product_id->type(2);
+            db_orders_lines_product_id->labelsize(16);
+            db_orders_lines_product_id->textsize(16);
+            db_orders_lines_product_id->align((FL_ALIGN_TOP_LEFT));
+            add_input_field_to_map("orders_lines", "product_id", db_orders_lines_product_id);
+          } // Fl_Int_Input* db_orders_lines_product_id
+          { db_orders_lines_description = new Fl_Input(101, 387, 444, 25, _tr("Description"));
+            db_orders_lines_description->tooltip(_tr("Type partal description to search on availlable products"));
+            db_orders_lines_description->labelsize(16);
+            db_orders_lines_description->textfont(1);
+            db_orders_lines_description->textsize(16);
+            db_orders_lines_description->align((FL_ALIGN_TOP_LEFT));
+            add_input_field_to_map("orders_lines", "description", db_orders_lines_description);
+          } // Fl_Input* db_orders_lines_description
+          { btnSearchProduct = new Fl_Button(555, 387, 30, 25, _tr("@<->"));
+            btnSearchProduct->tooltip(_tr("Show products search window"));
+            btnSearchProduct->labelsize(18);
+            btnSearchProduct->labelcolor(22);
+          } // Fl_Button* btnSearchProduct
+          { local o = db_orders_lines_quantity = new My_Fl_Float_Input(21, 435, 84, 25, _tr("Quantity"));
+            db_orders_lines_quantity->type(1);
+            db_orders_lines_quantity->box(FL_DOWN_BOX);
+            db_orders_lines_quantity->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_quantity->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_quantity->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_quantity->labelfont(1);
+            db_orders_lines_quantity->labelsize(16);
+            db_orders_lines_quantity->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_quantity->textfont(1);
+            db_orders_lines_quantity->textsize(16);
+            db_orders_lines_quantity->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_quantity->when(FL_WHEN_RELEASE);
+            o->decimal_places(-6);
+            add_input_field_to_map("orders_lines", "quantity", db_orders_lines_quantity);
+          } // My_Fl_Float_Input* db_orders_lines_quantity
+          { db_orders_lines_price = new My_Fl_Float_Input(115, 435, 108, 25, _tr("Price"));
+            db_orders_lines_price->type(1);
+            db_orders_lines_price->box(FL_DOWN_BOX);
+            db_orders_lines_price->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_price->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_price->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_price->labelfont(1);
+            db_orders_lines_price->labelsize(16);
+            db_orders_lines_price->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_price->textfont(1);
+            db_orders_lines_price->textsize(16);
+            db_orders_lines_price->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_price->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "price", db_orders_lines_price);
+          } // My_Fl_Float_Input* db_orders_lines_price
+          { db_orders_lines_price_decimals = new Fl_Int_Input(230, 435, 20, 25, _tr("(.)"));
+            db_orders_lines_price_decimals->tooltip(_tr("Number of decimals to use on calculations"));
+            db_orders_lines_price_decimals->type(2);
+            db_orders_lines_price_decimals->labelsize(16);
+            db_orders_lines_price_decimals->textsize(16);
+            db_orders_lines_price_decimals->align((FL_ALIGN_TOP));
+            add_input_field_to_map("orders_lines", "price_decimals", db_orders_lines_price_decimals);
+          } // Fl_Int_Input* db_orders_lines_price_decimals
+          { local o = db_orders_lines_weight = new My_Fl_Float_Input(255, 435, 70, 25, _tr("Weight"));
+            db_orders_lines_weight->type(1);
+            db_orders_lines_weight->box(FL_DOWN_BOX);
+            db_orders_lines_weight->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_weight->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_weight->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_weight->labelfont(0);
+            db_orders_lines_weight->labelsize(16);
+            db_orders_lines_weight->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_weight->textsize(16);
+            db_orders_lines_weight->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_weight->when(FL_WHEN_RELEASE);
+            o->decimal_places(-6);
+            add_input_field_to_map("orders_lines", "weight", db_orders_lines_weight);
+          } // My_Fl_Float_Input* db_orders_lines_weight
+          { db_orders_lines_first_total = new Fl_Float_Input_Fmt(330, 435, 100, 25, _tr("1st total"));
+            db_orders_lines_first_total->type(1);
+            db_orders_lines_first_total->box(FL_DOWN_BOX);
+            db_orders_lines_first_total->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_first_total->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_first_total->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_first_total->labelfont(0);
+            db_orders_lines_first_total->labelsize(16);
+            db_orders_lines_first_total->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_first_total->textsize(16);
+            db_orders_lines_first_total->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_first_total->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "first_total", db_orders_lines_first_total);
+          } // Fl_Float_Input_Fmt* db_orders_lines_first_total
+          { db_orders_lines_discount_pct = new My_Fl_Float_Input(435, 435, 60, 25, _tr("Disc. %"));
+            db_orders_lines_discount_pct->type(1);
+            db_orders_lines_discount_pct->box(FL_DOWN_BOX);
+            db_orders_lines_discount_pct->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_discount_pct->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_discount_pct->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_discount_pct->labelfont(0);
+            db_orders_lines_discount_pct->labelsize(16);
+            db_orders_lines_discount_pct->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_discount_pct->textsize(16);
+            db_orders_lines_discount_pct->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_discount_pct->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "discount_pct", db_orders_lines_discount_pct);
+          } // My_Fl_Float_Input* db_orders_lines_discount_pct
+          { db_orders_lines_discount_amt = new Fl_Float_Input_Fmt(505, 435, 80, 25, _tr("Disc. $"));
+            db_orders_lines_discount_amt->type(1);
+            db_orders_lines_discount_amt->box(FL_DOWN_BOX);
+            db_orders_lines_discount_amt->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_discount_amt->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_discount_amt->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_discount_amt->labelfont(0);
+            db_orders_lines_discount_amt->labelsize(16);
+            db_orders_lines_discount_amt->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_discount_amt->textsize(16);
+            db_orders_lines_discount_amt->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_discount_amt->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "discount_amt", db_orders_lines_discount_amt);
+          } // Fl_Float_Input_Fmt* db_orders_lines_discount_amt
+          { db_orders_lines_line_subtotal = new Fl_Float_Input_Fmt(21, 485, 108, 25, _tr("Subtotal"));
+            db_orders_lines_line_subtotal->type(1);
+            db_orders_lines_line_subtotal->box(FL_DOWN_BOX);
+            db_orders_lines_line_subtotal->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_line_subtotal->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_line_subtotal->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_line_subtotal->labelfont(0);
+            db_orders_lines_line_subtotal->labelsize(16);
+            db_orders_lines_line_subtotal->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_line_subtotal->textsize(16);
+            db_orders_lines_line_subtotal->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_line_subtotal->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "line_subtotal", db_orders_lines_line_subtotal);
+          } // Fl_Float_Input_Fmt* db_orders_lines_line_subtotal
+          { db_orders_lines_sales_tax2_pct = new Fl_Float_Input_Fmt(139, 485, 64, 25, _tr("R.E. %"));
+            db_orders_lines_sales_tax2_pct->type(1);
+            db_orders_lines_sales_tax2_pct->box(FL_DOWN_BOX);
+            db_orders_lines_sales_tax2_pct->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_sales_tax2_pct->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_sales_tax2_pct->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_sales_tax2_pct->labelfont(0);
+            db_orders_lines_sales_tax2_pct->labelsize(16);
+            db_orders_lines_sales_tax2_pct->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_sales_tax2_pct->textsize(16);
+            db_orders_lines_sales_tax2_pct->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_sales_tax2_pct->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "sales_tax2_pct", db_orders_lines_sales_tax2_pct);
+          } // Fl_Float_Input_Fmt* db_orders_lines_sales_tax2_pct
+          { db_orders_lines_sales_tax1_pct = new Fl_Float_Input_Fmt(213, 485, 64, 25, _tr("V.A.T. %"));
+            db_orders_lines_sales_tax1_pct->type(1);
+            db_orders_lines_sales_tax1_pct->box(FL_DOWN_BOX);
+            db_orders_lines_sales_tax1_pct->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_sales_tax1_pct->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_sales_tax1_pct->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_sales_tax1_pct->labelfont(0);
+            db_orders_lines_sales_tax1_pct->labelsize(16);
+            db_orders_lines_sales_tax1_pct->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_sales_tax1_pct->textsize(16);
+            db_orders_lines_sales_tax1_pct->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_sales_tax1_pct->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "sales_tax1_pct", db_orders_lines_sales_tax1_pct);
+          } // Fl_Float_Input_Fmt* db_orders_lines_sales_tax1_pct
+          { db_orders_lines_sales_tax1_amt = new Fl_Float_Input_Fmt(287, 485, 87, 25, _tr("V.A.T. $"));
+            db_orders_lines_sales_tax1_amt->type(1);
+            db_orders_lines_sales_tax1_amt->box(FL_DOWN_BOX);
+            db_orders_lines_sales_tax1_amt->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_sales_tax1_amt->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_sales_tax1_amt->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_sales_tax1_amt->labelfont(0);
+            db_orders_lines_sales_tax1_amt->labelsize(16);
+            db_orders_lines_sales_tax1_amt->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_sales_tax1_amt->textsize(16);
+            db_orders_lines_sales_tax1_amt->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_sales_tax1_amt->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "sales_tax1_amt", db_orders_lines_sales_tax1_amt);
+          } // Fl_Float_Input_Fmt* db_orders_lines_sales_tax1_amt
+          { btnSaveLine = new My_Fl_Return_Button(384, 485, 83, 25, _tr("Save"));
+            btnSaveLine->tooltip(_tr("Save the line currently edited"));
+            btnSaveLine->box(FL_UP_BOX);
+            btnSaveLine->color(FL_BACKGROUND_COLOR);
+            btnSaveLine->selection_color(FL_BACKGROUND_COLOR);
+            btnSaveLine->labeltype(FL_NORMAL_LABEL);
+            btnSaveLine->labelfont(1);
+            btnSaveLine->labelsize(16);
+            btnSaveLine->labelcolor(FL_FOREGROUND_COLOR);
+            btnSaveLine->align((FL_ALIGN_CENTER));
+            btnSaveLine->when(FL_WHEN_RELEASE);
+          } // My_Fl_Return_Button* btnSaveLine
+          { db_orders_lines_line_total = new Fl_Float_Input_Fmt(477, 485, 108, 25, _tr("Total"));
+            db_orders_lines_line_total->type(1);
+            db_orders_lines_line_total->box(FL_DOWN_BOX);
+            db_orders_lines_line_total->color(FL_BACKGROUND2_COLOR);
+            db_orders_lines_line_total->selection_color(FL_SELECTION_COLOR);
+            db_orders_lines_line_total->labeltype(FL_NORMAL_LABEL);
+            db_orders_lines_line_total->labelfont(1);
+            db_orders_lines_line_total->labelsize(16);
+            db_orders_lines_line_total->labelcolor(FL_FOREGROUND_COLOR);
+            db_orders_lines_line_total->textfont(1);
+            db_orders_lines_line_total->textsize(16);
+            db_orders_lines_line_total->align((FL_ALIGN_TOP_LEFT));
+            db_orders_lines_line_total->when(FL_WHEN_RELEASE);
+            add_input_field_to_map("orders_lines", "line_total", db_orders_lines_line_total);
+          } // Fl_Float_Input_Fmt* db_orders_lines_line_total
+          group_lines->end();
+        } // Fl_Group* group_lines
+        { tabLineNotes = new Fl_Group(10, 320, 585, 200, _tr("Line Notes"));
+          tabLineNotes->labelfont(2);
+          tabLineNotes->labelsize(16);
+          tabLineNotes->hide();
+          { db_orders_lines_notes = new Fl_Input(80, 330, 505, 180, _tr("Notes"));
+            db_orders_lines_notes->tooltip(_tr("Type partal description to search on availlable products"));
+            db_orders_lines_notes->type(4);
+            db_orders_lines_notes->labelsize(16);
+            db_orders_lines_notes->textsize(16);
+            add_input_field_to_map("orders_lines", "notes", db_orders_lines_notes);
+          } // Fl_Input* db_orders_lines_notes
+          tabLineNotes->end();
+        } // Fl_Group* tabLineNotes
+        { tabDues = new Fl_Group(10, 320, 585, 200, _tr("Dues"));
+          tabDues->labelfont(2);
+          tabDues->labelsize(16);
+          tabDues->hide();
+          { grid_dues = new Fl_Data_Table(15, 330, 575, 130);
+            grid_dues->box(FL_NO_BOX);
+            grid_dues->color(FL_BACKGROUND2_COLOR);
+            grid_dues->selection_color(FL_SELECTION_COLOR);
+            grid_dues->labeltype(FL_NORMAL_LABEL);
+            grid_dues->labelfont(0);
+            grid_dues->labelsize(16);
+            grid_dues->labelcolor(FL_FOREGROUND_COLOR);
+            grid_dues->textsize(16);
+            grid_dues->align((FL_ALIGN_BOTTOM));
+            grid_dues->when(FL_WHEN_RELEASE_ALWAYS);
+          } // Fl_Data_Table* grid_dues
+          { local o = due_id = new Fl_Output(15, 485, 80, 25, _tr("ID"));
+            due_id->labelsize(16);
+            due_id->textsize(16);
+            due_id->align((FL_ALIGN_TOP_LEFT));
+            o->right_to_left(1);
+          } // Fl_Output* due_id
+          { due_date = new Fl_Input(100, 485, 125, 25, _tr("Due"));
+            due_date->labelsize(16);
+            due_date->textfont(1);
+            due_date->textsize(16);
+            due_date->align((FL_ALIGN_TOP_LEFT));
+          } // Fl_Input* due_date
+          { btnShowCalendarDueDate = new Fl_Button(230, 485, 30, 25, _tr("@<->"));
+            btnShowCalendarDueDate->tooltip(_tr("Show calendar"));
+            btnShowCalendarDueDate->labelsize(18);
+            btnShowCalendarDueDate->labelcolor(22);
+          } // Fl_Button* btnShowCalendarDueDate
+          { due_pct = new Fl_Float_Input_Fmt(270, 485, 80, 25, _tr("Pct. %"));
+            due_pct->type(1);
+            due_pct->box(FL_DOWN_BOX);
+            due_pct->color(FL_BACKGROUND2_COLOR);
+            due_pct->selection_color(FL_SELECTION_COLOR);
+            due_pct->labeltype(FL_NORMAL_LABEL);
+            due_pct->labelfont(1);
+            due_pct->labelsize(16);
+            due_pct->labelcolor(FL_FOREGROUND_COLOR);
+            due_pct->textfont(1);
+            due_pct->textsize(16);
+            due_pct->align((FL_ALIGN_TOP_LEFT));
+            due_pct->when(FL_WHEN_RELEASE);
+          } // Fl_Float_Input_Fmt* due_pct
+          { due_amount = new Fl_Float_Input_Fmt(355, 485, 120, 25, _tr("Amount"));
+            due_amount->type(1);
+            due_amount->box(FL_DOWN_BOX);
+            due_amount->color(FL_BACKGROUND2_COLOR);
+            due_amount->selection_color(FL_SELECTION_COLOR);
+            due_amount->labeltype(FL_NORMAL_LABEL);
+            due_amount->labelfont(1);
+            due_amount->labelsize(16);
+            due_amount->labelcolor(FL_FOREGROUND_COLOR);
+            due_amount->textfont(1);
+            due_amount->textsize(16);
+            due_amount->align((FL_ALIGN_TOP_LEFT));
+            due_amount->when(FL_WHEN_RELEASE);
+          } // Fl_Float_Input_Fmt* due_amount
+          { btnDueSave = new My_Fl_Return_Button(485, 485, 100, 25, _tr("Save"));
+            btnDueSave->box(FL_UP_BOX);
+            btnDueSave->color(FL_BACKGROUND_COLOR);
+            btnDueSave->selection_color(FL_BACKGROUND_COLOR);
+            btnDueSave->labeltype(FL_NORMAL_LABEL);
+            btnDueSave->labelfont(0);
+            btnDueSave->labelsize(16);
+            btnDueSave->labelcolor(FL_FOREGROUND_COLOR);
+            btnDueSave->align((FL_ALIGN_CENTER));
+            btnDueSave->when(FL_WHEN_RELEASE);
+          } // My_Fl_Return_Button* btnDueSave
+          tabDues->end();
+        } // Fl_Group* tabDues
+        { tabPayments = new Fl_Group(10, 320, 585, 200, _tr("Payments"));
+          tabPayments->labelfont(2);
+          tabPayments->labelsize(16);
+          tabPayments->hide();
+          { grid_payments = new Fl_Data_Table(15, 330, 575, 130);
+            grid_payments->box(FL_NO_BOX);
+            grid_payments->color(FL_BACKGROUND2_COLOR);
+            grid_payments->selection_color(FL_SELECTION_COLOR);
+            grid_payments->labeltype(FL_NORMAL_LABEL);
+            grid_payments->labelfont(0);
+            grid_payments->labelsize(16);
+            grid_payments->labelcolor(FL_FOREGROUND_COLOR);
+            grid_payments->textsize(16);
+            grid_payments->align((FL_ALIGN_BOTTOM));
+            grid_payments->when(FL_WHEN_RELEASE_ALWAYS);
+          } // Fl_Data_Table* grid_payments
+          { local o = payment_id = new Fl_Output(15, 485, 80, 25, _tr("ID"));
+            payment_id->labelsize(16);
+            payment_id->textsize(16);
+            payment_id->align((FL_ALIGN_TOP_LEFT));
+            o->right_to_left(1);
+          } // Fl_Output* payment_id
+          { payment_date = new Fl_Input(100, 485, 125, 25, _tr("Date"));
+            payment_date->labelsize(16);
+            payment_date->textfont(1);
+            payment_date->textsize(16);
+            payment_date->align((FL_ALIGN_TOP_LEFT));
+          } // Fl_Input* payment_date
+          { btnShowCalendarPaymentDate = new Fl_Button(230, 485, 30, 25, _tr("@<->"));
+            btnShowCalendarPaymentDate->tooltip(_tr("Show calendar"));
+            btnShowCalendarPaymentDate->labelsize(18);
+            btnShowCalendarPaymentDate->labelcolor(22);
+          } // Fl_Button* btnShowCalendarPaymentDate
+          { payemnt_amount = new Fl_Float_Input_Fmt(270, 485, 120, 25, _tr("Amount"));
+            payemnt_amount->type(1);
+            payemnt_amount->box(FL_DOWN_BOX);
+            payemnt_amount->color(FL_BACKGROUND2_COLOR);
+            payemnt_amount->selection_color(FL_SELECTION_COLOR);
+            payemnt_amount->labeltype(FL_NORMAL_LABEL);
+            payemnt_amount->labelfont(1);
+            payemnt_amount->labelsize(16);
+            payemnt_amount->labelcolor(FL_FOREGROUND_COLOR);
+            payemnt_amount->textfont(1);
+            payemnt_amount->textsize(16);
+            payemnt_amount->align((FL_ALIGN_TOP_LEFT));
+            payemnt_amount->when(FL_WHEN_RELEASE);
+          } // Fl_Float_Input_Fmt* payemnt_amount
+          { btnPaymentSave = new My_Fl_Return_Button(395, 485, 100, 25, _tr("Save"));
+            btnPaymentSave->box(FL_UP_BOX);
+            btnPaymentSave->color(FL_BACKGROUND_COLOR);
+            btnPaymentSave->selection_color(FL_BACKGROUND_COLOR);
+            btnPaymentSave->labeltype(FL_NORMAL_LABEL);
+            btnPaymentSave->labelfont(0);
+            btnPaymentSave->labelsize(16);
+            btnPaymentSave->labelcolor(FL_FOREGROUND_COLOR);
+            btnPaymentSave->align((FL_ALIGN_CENTER));
+            btnPaymentSave->when(FL_WHEN_RELEASE);
+          } // My_Fl_Return_Button* btnPaymentSave
+          tabPayments->end();
+        } // Fl_Group* tabPayments
+        linesTab->end();
+      } // Fl_Tabs* linesTab
+      o->end();
+    } // Fl_Group* o
+    { btnNumberOrder = new My_Fl_Return_Button(230, 525, 82, 25, _tr("Number"));
+      btnNumberOrder->box(FL_UP_BOX);
+      btnNumberOrder->color(FL_BACKGROUND_COLOR);
+      btnNumberOrder->selection_color(FL_BACKGROUND_COLOR);
+      btnNumberOrder->labeltype(FL_NORMAL_LABEL);
+      btnNumberOrder->labelfont(0);
+      btnNumberOrder->labelsize(16);
+      btnNumberOrder->labelcolor(FL_FOREGROUND_COLOR);
+      btnNumberOrder->align((FL_ALIGN_CENTER));
+      btnNumberOrder->when(FL_WHEN_RELEASE);
+    } // My_Fl_Return_Button* btnNumberOrder
+    { dbAction = new Fl_Button(10, 525, 119, 25);
+      dbAction->resize(9, 525, 119, 25);
+      dbAction->down_box(FL_BORDER_BOX);
+      dbAction->labeltype(FL_NO_LABEL);
+      dbAction->labelsize(16);
+      dbAction->textsize(16);
+    } // Fl_Choice* dbAction
+    { btnDbAction = new My_Fl_Return_Button(138, 525, 82, 25, _tr("Action"));
+      btnDbAction->resize(138, 525, 82, 25);
+      btnDbAction->label(_tr("Action"));
+      btnDbAction->tooltip(_tr("Perform the selected action on this order"));
+      btnDbAction->box(FL_UP_BOX);
+      btnDbAction->color(FL_BACKGROUND_COLOR);
+      btnDbAction->selection_color(FL_BACKGROUND_COLOR);
+      btnDbAction->labeltype(FL_NORMAL_LABEL);
+      btnDbAction->labelfont(1);
+      btnDbAction->labelsize(16);
+      btnDbAction->labelcolor(FL_FOREGROUND_COLOR);
+      btnDbAction->align((FL_ALIGN_CENTER));
+      btnDbAction->when(FL_WHEN_RELEASE);
+    } // My_Fl_Return_Button* btnDbAction
+    tabMain->end();
+    Fl_Group.current()->resizable(tabMain);
+  } // Fl_Group* tabMain
+  { tabDelivery = new Fl_Group(5, 95, 790, 460, _tr("Delivery"));
+    tabDelivery->color(246);
+    tabDelivery->labelfont(2);
+    tabDelivery->labelsize(16);
+    tabDelivery->hide();
+    { db_orders_entity_address = new Fl_Input(91, 105, 694, 25, _tr("Address"));
+      db_orders_entity_address->labelsize(16);
+      db_orders_entity_address->textsize(16);
+      add_input_field_to_map("orders", "entity_address", db_orders_entity_address);
+    } // Fl_Input* db_orders_entity_address
+    { db_orders_entity_zip = new Fl_Input(91, 135, 95, 25, _tr("ZIP"));
+      db_orders_entity_zip->labelsize(16);
+      db_orders_entity_zip->textsize(16);
+      add_input_field_to_map("orders", "entity_zip", db_orders_entity_zip);
+    } // Fl_Input* db_orders_entity_zip
+    { db_orders_entity_city = new Fl_Input(288, 135, 497, 25, _tr("City"));
+      db_orders_entity_city->labelsize(16);
+      db_orders_entity_city->textsize(16);
+      add_input_field_to_map("orders", "entity_city", db_orders_entity_city);
+    } // Fl_Input* db_orders_entity_city
+    { db_orders_entity_state = new Fl_Input(91, 165, 407, 25, _tr("State"));
+      db_orders_entity_state->labelsize(16);
+      db_orders_entity_state->textsize(16);
+      add_input_field_to_map("orders", "entity_state", db_orders_entity_state);
+    } // Fl_Input* db_orders_entity_state
+    { db_orders_entity_country = new Fl_Input(585, 165, 201, 25, _tr("Country"));
+      db_orders_entity_country->labelsize(16);
+      db_orders_entity_country->textsize(16);
+      add_input_field_to_map("orders", "entity_country", db_orders_entity_country);
+    } // Fl_Input* db_orders_entity_country
+    { db_orders_entity_phone = new Fl_Input(91, 195, 201, 25, _tr("Phone"));
+      db_orders_entity_phone->labelsize(16);
+      db_orders_entity_phone->textsize(16);
+      add_input_field_to_map("orders", "entity_phone", db_orders_entity_phone);
+    } // Fl_Input* db_orders_entity_phone
+    { db_orders_entity_tax_number = new Fl_Input(585, 195, 200, 25, _tr("Tax Num."));
+      db_orders_entity_tax_number->labelsize(16);
+      db_orders_entity_tax_number->textsize(16);
+      add_input_field_to_map("orders", "entity_tax_number", db_orders_entity_tax_number);
+    } // Fl_Input* db_orders_entity_tax_number
+    { db_orders_order_valid_till_date = new Fl_Input(90, 225, 121, 25, _tr("Valid till"));
+      db_orders_order_valid_till_date->labelsize(16);
+      db_orders_order_valid_till_date->textsize(16);
+      add_input_field_to_map("orders", "order_valid_till_date", db_orders_order_valid_till_date);
+    } // Fl_Input* db_orders_order_valid_till_date
+    { btnShowCalendarValidTill = new Fl_Button(221, 225, 30, 25, _tr("@<->"));
+      btnShowCalendarValidTill->tooltip(_tr("Show calendar"));
+      btnShowCalendarValidTill->labelsize(18);
+      btnShowCalendarValidTill->labelcolor(22);
+    } // Fl_Button* btnShowCalendarValidTill
+    { db_orders_entity_use_sales_tax2 = new Fl_Check_Button(585, 225, 155, 25, _tr("Use Sales Tax II"));
+      db_orders_entity_use_sales_tax2->down_box(FL_DOWN_BOX);
+      db_orders_entity_use_sales_tax2->labelsize(16);
+      add_input_field_to_map("orders", "entity_use_sales_tax2", db_orders_entity_use_sales_tax2);
+    } // Fl_Check_Button* db_orders_entity_use_sales_tax2
+    { db_orders_entity_sales_tax_exempt = new Fl_Check_Button(585, 255, 155, 25, _tr("Sales Tax Exempt"));
+      db_orders_entity_sales_tax_exempt->down_box(FL_DOWN_BOX);
+      db_orders_entity_sales_tax_exempt->labelsize(16);
+      add_input_field_to_map("orders", "entity_sales_tax_exempt", db_orders_entity_sales_tax_exempt);
+    } // Fl_Check_Button* db_orders_entity_sales_tax_exempt
+    { db_orders_notes = new Fl_Text_Editor_Buffered(15, 395, 770, 150, _tr("Notes"));
+      db_orders_notes->box(FL_DOWN_FRAME);
+      db_orders_notes->color(FL_BACKGROUND2_COLOR);
+      db_orders_notes->selection_color(FL_SELECTION_COLOR);
+      db_orders_notes->labeltype(FL_NORMAL_LABEL);
+      db_orders_notes->labelfont(0);
+      db_orders_notes->labelsize(16);
+      db_orders_notes->labelcolor(FL_FOREGROUND_COLOR);
+      db_orders_notes->textsize(16);
+      db_orders_notes->align((FL_ALIGN_TOP_LEFT));
+      db_orders_notes->when(FL_WHEN_RELEASE);
+      Fl_Group.current()->resizable(db_orders_notes);
+      add_input_field_to_map("orders", "notes", db_orders_notes);
+    } // Fl_Text_Editor_Buffered* db_orders_notes
+    { local o = new Fl_Check_Button(125, 375, 125, 25, _tr("Wrap lines"));
+      o->down_box(FL_DOWN_BOX);
+      o->value(1);
+      o->labelsize(16);
+      o->callback(cb_Wrap);
+    } // Fl_Check_Button* o
+    { db_orders_irpf_pct_retention = new Fl_Float_Input_Fmt(585, 285, 70, 25, _tr("I.R.P.F. %"));
+      db_orders_irpf_pct_retention->type(1);
+      db_orders_irpf_pct_retention->box(FL_DOWN_BOX);
+      db_orders_irpf_pct_retention->color(FL_BACKGROUND2_COLOR);
+      db_orders_irpf_pct_retention->selection_color(FL_SELECTION_COLOR);
+      db_orders_irpf_pct_retention->labeltype(FL_NORMAL_LABEL);
+      db_orders_irpf_pct_retention->labelfont(0);
+      db_orders_irpf_pct_retention->labelsize(16);
+      db_orders_irpf_pct_retention->labelcolor(FL_FOREGROUND_COLOR);
+      db_orders_irpf_pct_retention->textsize(16);
+      db_orders_irpf_pct_retention->align((FL_ALIGN_RIGHT));
+      db_orders_irpf_pct_retention->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("orders", "irpf_pct_retention", db_orders_irpf_pct_retention);
+    } // Fl_Float_Input_Fmt* db_orders_irpf_pct_retention
+    tabDelivery->end();
+  } // Fl_Group* tabDelivery
+  { tabOptions = new Fl_Group(5, 95, 790, 460, _tr("Options"));
+    tabOptions->color(246);
+    tabOptions->labelfont(2);
+    tabOptions->labelsize(16);
+    tabOptions->hide();
+    { opt_ask_for_printer = new Fl_Check_Button(20, 115, 155, 25, _tr("Ask for printer"));
+      opt_ask_for_printer->down_box(FL_DOWN_BOX);
+      opt_ask_for_printer->labelsize(16);
+    } // Fl_Check_Button* opt_ask_for_printer
+    { opt_print_only_data = new Fl_Check_Button(20, 150, 155, 25, _tr("Print only data"));
+      opt_print_only_data->down_box(FL_DOWN_BOX);
+      opt_print_only_data->labelsize(16);
+    } // Fl_Check_Button* opt_print_only_data
+    { opt_print_to_pdf = new Fl_Check_Button(20, 180, 155, 25, _tr("Print to PDF"));
+      opt_print_to_pdf->down_box(FL_DOWN_BOX);
+      opt_print_to_pdf->labelsize(16);
+    } // Fl_Check_Button* opt_print_to_pdf
+    { opt_print_page_format = new Fl_Choice_Str(20, 215, 130, 25);
+      opt_print_page_format->box(FL_FLAT_BOX);
+      opt_print_page_format->down_box(FL_BORDER_BOX);
+      opt_print_page_format->color(FL_BACKGROUND_COLOR);
+      opt_print_page_format->selection_color(FL_SELECTION_COLOR);
+      opt_print_page_format->labeltype(FL_NO_LABEL);
+      opt_print_page_format->labelfont(0);
+      opt_print_page_format->labelsize(16);
+      opt_print_page_format->labelcolor(FL_FOREGROUND_COLOR);
+      opt_print_page_format->textsize(16);
+      opt_print_page_format->align((FL_ALIGN_LEFT));
+      opt_print_page_format->when(FL_WHEN_RELEASE);
+    } // Fl_Choice_Str* opt_print_page_format
+    { btnOptPrint = new Fl_Button(20, 250, 130, 25, _tr("Print"));
+      btnOptPrint->tooltip(_tr("Print the current order"));
+      btnOptPrint->labelsize(16);
+    } // Fl_Button* btnOptPrint
+    { opt_email_program = new Fl_Input(260, 145, 520, 25, _tr("Email program"));
+      opt_email_program->tooltip(_tr("Type partal description to search on availlable entities"));
+      opt_email_program->labelsize(16);
+      opt_email_program->textsize(16);
+      opt_email_program->align((FL_ALIGN_TOP_LEFT));
+    } // Fl_Input* opt_email_program
+    { opt_email_program_command = new Fl_Input(260, 210, 520, 25, _tr("Email program parameters"));
+      opt_email_program_command->tooltip(_tr("Type partal description to search on availlable entities"));
+      opt_email_program_command->labelsize(16);
+      opt_email_program_command->textsize(16);
+      opt_email_program_command->align((FL_ALIGN_TOP_LEFT));
+    } // Fl_Input* opt_email_program_command
+    { btnOptSendEmail = new Fl_Button(260, 250, 130, 25, _tr("Send as email"));
+      btnOptSendEmail->tooltip(_tr("Print the current order"));
+      btnOptSendEmail->labelsize(16);
+    } // Fl_Button* btnOptSendEmail
+    { opt_print_order_company_info = new Fl_Text_Editor_Buffered(20, 350, 375, 200, _tr("Company Info"));
+      opt_print_order_company_info->box(FL_DOWN_FRAME);
+      opt_print_order_company_info->color(FL_BACKGROUND2_COLOR);
+      opt_print_order_company_info->selection_color(FL_SELECTION_COLOR);
+      opt_print_order_company_info->labeltype(FL_NORMAL_LABEL);
+      opt_print_order_company_info->labelfont(0);
+      opt_print_order_company_info->labelsize(16);
+      opt_print_order_company_info->labelcolor(FL_FOREGROUND_COLOR);
+      opt_print_order_company_info->textsize(16);
+      opt_print_order_company_info->align((FL_ALIGN_TOP_LEFT));
+      opt_print_order_company_info->when(FL_WHEN_RELEASE);
+    } // Fl_Text_Editor_Buffered* opt_print_order_company_info
+    { local o = new Fl_Check_Button(200, 330, 125, 25, _tr("Wrap lines"));
+      o->down_box(FL_DOWN_BOX);
+      o->value(1);
+      o->labelsize(16);
+      o->callback(cb_Wrap1);
+    } // Fl_Check_Button* o
+    { opt_print_order_bottom_info = new Fl_Text_Editor_Buffered(405, 350, 375, 200, _tr("Company Info"));
+      opt_print_order_bottom_info->box(FL_DOWN_FRAME);
+      opt_print_order_bottom_info->color(FL_BACKGROUND2_COLOR);
+      opt_print_order_bottom_info->selection_color(FL_SELECTION_COLOR);
+      opt_print_order_bottom_info->labeltype(FL_NORMAL_LABEL);
+      opt_print_order_bottom_info->labelfont(0);
+      opt_print_order_bottom_info->labelsize(16);
+      opt_print_order_bottom_info->labelcolor(FL_FOREGROUND_COLOR);
+      opt_print_order_bottom_info->textsize(16);
+      opt_print_order_bottom_info->align((FL_ALIGN_TOP_LEFT));
+      opt_print_order_bottom_info->when(FL_WHEN_RELEASE);
+      Fl_Group.current()->resizable(opt_print_order_bottom_info);
+    } // Fl_Text_Editor_Buffered* opt_print_order_bottom_info
+    { local o = new Fl_Check_Button(590, 330, 125, 25, _tr("Wrap lines"));
+      o->down_box(FL_DOWN_BOX);
+      o->value(1);
+      o->labelsize(16);
+      o->callback(cb_Wrap2);
+    } // Fl_Check_Button* o
+    tabOptions->end();
+  } // Fl_Group* tabOptions
+  { tabChartStatistics = new Fl_Group(5, 95, 790, 460, _tr("Statistics"));
+    tabChartStatistics->color(246);
+    tabChartStatistics->labelfont(2);
+    tabChartStatistics->labelsize(16);
+    tabChartStatistics->hide();
+    tabChartStatistics->end();
+  } // Fl_Group* tabChartStatistics
+  { tabHistory = new Fl_Group(5, 95, 790, 460, _tr("History"));
+    tabHistory->color(246);
+    tabHistory->labelfont(2);
+    tabHistory->labelsize(16);
+    tabHistory->hide();
+    tabHistory->end();
+  } // Fl_Group* tabHistory
+  { tabPrintPreview = new Fl_Group(5, 95, 790, 460, _tr("Preview"));
+    tabPrintPreview->color(246);
+    tabPrintPreview->labelfont(2);
+    tabPrintPreview->labelsize(16);
+    tabPrintPreview->hide();
+    tabPrintPreview->end();
+  } // Fl_Group* tabPrintPreview
+  { tabTotals = new Fl_Group(5, 95, 790, 460, _tr("Totals"));
+    tabTotals->color(246);
+    tabTotals->labelfont(2);
+    tabTotals->labelsize(16);
+    tabTotals->hide();
+    { totals_balance = new Fl_Float_Input_Fmt(145, 155, 110, 25, _tr("Balance"));
+      totals_balance->type(1);
+      totals_balance->box(FL_DOWN_BOX);
+      totals_balance->color(FL_BACKGROUND2_COLOR);
+      totals_balance->selection_color(FL_SELECTION_COLOR);
+      totals_balance->labeltype(FL_NORMAL_LABEL);
+      totals_balance->labelfont(0);
+      totals_balance->labelsize(16);
+      totals_balance->labelcolor(FL_FOREGROUND_COLOR);
+      totals_balance->textsize(16);
+      totals_balance->align((FL_ALIGN_LEFT));
+      totals_balance->when(FL_WHEN_RELEASE);
+    } // Fl_Float_Input_Fmt* totals_balance
+    { db_totals_overview_sales_quoted = new Fl_Float_Input_Fmt(145, 200, 110, 25, _tr("Sales Quoted"));
+      db_totals_overview_sales_quoted->type(1);
+      db_totals_overview_sales_quoted->box(FL_DOWN_BOX);
+      db_totals_overview_sales_quoted->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_sales_quoted->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_sales_quoted->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_sales_quoted->labelfont(0);
+      db_totals_overview_sales_quoted->labelsize(16);
+      db_totals_overview_sales_quoted->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_sales_quoted->textsize(16);
+      db_totals_overview_sales_quoted->align((FL_ALIGN_LEFT));
+      db_totals_overview_sales_quoted->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "sales_quoted", db_totals_overview_sales_quoted);
+    } // Fl_Float_Input_Fmt* db_totals_overview_sales_quoted
+    { db_totals_overview_sales_ordered = new Fl_Float_Input_Fmt(145, 235, 110, 25, _tr("Sales Ordered"));
+      db_totals_overview_sales_ordered->type(1);
+      db_totals_overview_sales_ordered->box(FL_DOWN_BOX);
+      db_totals_overview_sales_ordered->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_sales_ordered->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_sales_ordered->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_sales_ordered->labelfont(0);
+      db_totals_overview_sales_ordered->labelsize(16);
+      db_totals_overview_sales_ordered->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_sales_ordered->textsize(16);
+      db_totals_overview_sales_ordered->align((FL_ALIGN_LEFT));
+      db_totals_overview_sales_ordered->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "sales_ordered", db_totals_overview_sales_ordered);
+    } // Fl_Float_Input_Fmt* db_totals_overview_sales_ordered
+    { db_totals_overview_sales_delivered = new Fl_Float_Input_Fmt(145, 270, 110, 25, _tr("Sales Delivered"));
+      db_totals_overview_sales_delivered->type(1);
+      db_totals_overview_sales_delivered->box(FL_DOWN_BOX);
+      db_totals_overview_sales_delivered->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_sales_delivered->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_sales_delivered->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_sales_delivered->labelfont(0);
+      db_totals_overview_sales_delivered->labelsize(16);
+      db_totals_overview_sales_delivered->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_sales_delivered->textsize(16);
+      db_totals_overview_sales_delivered->align((FL_ALIGN_LEFT));
+      db_totals_overview_sales_delivered->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "sales_delivered", db_totals_overview_sales_delivered);
+    } // Fl_Float_Input_Fmt* db_totals_overview_sales_delivered
+    { db_totals_overview_sales_invoiced = new Fl_Float_Input_Fmt(145, 305, 110, 25, _tr("Sales Invoiced"));
+      db_totals_overview_sales_invoiced->type(1);
+      db_totals_overview_sales_invoiced->box(FL_DOWN_BOX);
+      db_totals_overview_sales_invoiced->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_sales_invoiced->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_sales_invoiced->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_sales_invoiced->labelfont(0);
+      db_totals_overview_sales_invoiced->labelsize(16);
+      db_totals_overview_sales_invoiced->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_sales_invoiced->textsize(16);
+      db_totals_overview_sales_invoiced->align((FL_ALIGN_LEFT));
+      db_totals_overview_sales_invoiced->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "sales_invoiced", db_totals_overview_sales_invoiced);
+    } // Fl_Float_Input_Fmt* db_totals_overview_sales_invoiced
+    { db_totals_overview_sales_discount = new Fl_Float_Input_Fmt(145, 340, 110, 25, _tr("Sales Discount"));
+      db_totals_overview_sales_discount->type(1);
+      db_totals_overview_sales_discount->box(FL_DOWN_BOX);
+      db_totals_overview_sales_discount->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_sales_discount->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_sales_discount->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_sales_discount->labelfont(0);
+      db_totals_overview_sales_discount->labelsize(16);
+      db_totals_overview_sales_discount->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_sales_discount->textsize(16);
+      db_totals_overview_sales_discount->align((FL_ALIGN_LEFT));
+      db_totals_overview_sales_discount->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "sales_discount", db_totals_overview_sales_discount);
+    } // Fl_Float_Input_Fmt* db_totals_overview_sales_discount
+    { db_totals_overview_sales_tax1 = new Fl_Float_Input_Fmt(145, 375, 110, 25, _tr("Sales Tax1"));
+      db_totals_overview_sales_tax1->type(1);
+      db_totals_overview_sales_tax1->box(FL_DOWN_BOX);
+      db_totals_overview_sales_tax1->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_sales_tax1->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_sales_tax1->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_sales_tax1->labelfont(0);
+      db_totals_overview_sales_tax1->labelsize(16);
+      db_totals_overview_sales_tax1->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_sales_tax1->textsize(16);
+      db_totals_overview_sales_tax1->align((FL_ALIGN_LEFT));
+      db_totals_overview_sales_tax1->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "sales_tax1", db_totals_overview_sales_tax1);
+    } // Fl_Float_Input_Fmt* db_totals_overview_sales_tax1
+    { db_totals_overview_sales_tax2 = new Fl_Float_Input_Fmt(145, 410, 110, 25, _tr("Sales Tax2"));
+      db_totals_overview_sales_tax2->type(1);
+      db_totals_overview_sales_tax2->box(FL_DOWN_BOX);
+      db_totals_overview_sales_tax2->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_sales_tax2->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_sales_tax2->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_sales_tax2->labelfont(0);
+      db_totals_overview_sales_tax2->labelsize(16);
+      db_totals_overview_sales_tax2->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_sales_tax2->textsize(16);
+      db_totals_overview_sales_tax2->align((FL_ALIGN_LEFT));
+      db_totals_overview_sales_tax2->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "sales_tax2", db_totals_overview_sales_tax2);
+    } // Fl_Float_Input_Fmt* db_totals_overview_sales_tax2
+    { db_totals_overview_sales_paid = new Fl_Float_Input_Fmt(145, 445, 110, 25, _tr("Sales Paid"));
+      db_totals_overview_sales_paid->type(1);
+      db_totals_overview_sales_paid->box(FL_DOWN_BOX);
+      db_totals_overview_sales_paid->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_sales_paid->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_sales_paid->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_sales_paid->labelfont(0);
+      db_totals_overview_sales_paid->labelsize(16);
+      db_totals_overview_sales_paid->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_sales_paid->textsize(16);
+      db_totals_overview_sales_paid->align((FL_ALIGN_LEFT));
+      db_totals_overview_sales_paid->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "sales_paid", db_totals_overview_sales_paid);
+    } // Fl_Float_Input_Fmt* db_totals_overview_sales_paid
+    { btnRefreshTotals = new My_Fl_Return_Button(415, 155, 110, 25, _tr("Refresh"));
+      btnRefreshTotals->box(FL_UP_BOX);
+      btnRefreshTotals->color(FL_BACKGROUND_COLOR);
+      btnRefreshTotals->selection_color(FL_BACKGROUND_COLOR);
+      btnRefreshTotals->labeltype(FL_NORMAL_LABEL);
+      btnRefreshTotals->labelfont(0);
+      btnRefreshTotals->labelsize(16);
+      btnRefreshTotals->labelcolor(FL_FOREGROUND_COLOR);
+      btnRefreshTotals->align((FL_ALIGN_CENTER));
+      btnRefreshTotals->when(FL_WHEN_RELEASE);
+    } // My_Fl_Return_Button* btnRefreshTotals
+    { db_totals_overview_buys_quoted = new Fl_Float_Input_Fmt(415, 200, 110, 25, _tr("Buys Quoted"));
+      db_totals_overview_buys_quoted->type(1);
+      db_totals_overview_buys_quoted->box(FL_DOWN_BOX);
+      db_totals_overview_buys_quoted->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_buys_quoted->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_buys_quoted->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_buys_quoted->labelfont(0);
+      db_totals_overview_buys_quoted->labelsize(16);
+      db_totals_overview_buys_quoted->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_buys_quoted->textsize(16);
+      db_totals_overview_buys_quoted->align((FL_ALIGN_LEFT));
+      db_totals_overview_buys_quoted->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "buys_quoted", db_totals_overview_buys_quoted);
+    } // Fl_Float_Input_Fmt* db_totals_overview_buys_quoted
+    { db_totals_overview_buys_ordered = new Fl_Float_Input_Fmt(415, 235, 110, 25, _tr("Buys Ordered"));
+      db_totals_overview_buys_ordered->type(1);
+      db_totals_overview_buys_ordered->box(FL_DOWN_BOX);
+      db_totals_overview_buys_ordered->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_buys_ordered->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_buys_ordered->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_buys_ordered->labelfont(0);
+      db_totals_overview_buys_ordered->labelsize(16);
+      db_totals_overview_buys_ordered->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_buys_ordered->textsize(16);
+      db_totals_overview_buys_ordered->align((FL_ALIGN_LEFT));
+      db_totals_overview_buys_ordered->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "buys_ordered", db_totals_overview_buys_ordered);
+    } // Fl_Float_Input_Fmt* db_totals_overview_buys_ordered
+    { db_totals_overview_buys_received = new Fl_Float_Input_Fmt(415, 270, 110, 25, _tr("Buys Received"));
+      db_totals_overview_buys_received->type(1);
+      db_totals_overview_buys_received->box(FL_DOWN_BOX);
+      db_totals_overview_buys_received->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_buys_received->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_buys_received->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_buys_received->labelfont(0);
+      db_totals_overview_buys_received->labelsize(16);
+      db_totals_overview_buys_received->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_buys_received->textsize(16);
+      db_totals_overview_buys_received->align((FL_ALIGN_LEFT));
+      db_totals_overview_buys_received->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "buys_received", db_totals_overview_buys_received);
+    } // Fl_Float_Input_Fmt* db_totals_overview_buys_received
+    { db_totals_overview_buys_invoiced = new Fl_Float_Input_Fmt(415, 305, 110, 25, _tr("Buys Invoiced"));
+      db_totals_overview_buys_invoiced->type(1);
+      db_totals_overview_buys_invoiced->box(FL_DOWN_BOX);
+      db_totals_overview_buys_invoiced->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_buys_invoiced->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_buys_invoiced->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_buys_invoiced->labelfont(0);
+      db_totals_overview_buys_invoiced->labelsize(16);
+      db_totals_overview_buys_invoiced->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_buys_invoiced->textsize(16);
+      db_totals_overview_buys_invoiced->align((FL_ALIGN_LEFT));
+      db_totals_overview_buys_invoiced->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "buys_invoiced", db_totals_overview_buys_invoiced);
+    } // Fl_Float_Input_Fmt* db_totals_overview_buys_invoiced
+    { db_totals_overview_buys_discount = new Fl_Float_Input_Fmt(415, 340, 110, 25, _tr("Buys Discount"));
+      db_totals_overview_buys_discount->type(1);
+      db_totals_overview_buys_discount->box(FL_DOWN_BOX);
+      db_totals_overview_buys_discount->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_buys_discount->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_buys_discount->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_buys_discount->labelfont(0);
+      db_totals_overview_buys_discount->labelsize(16);
+      db_totals_overview_buys_discount->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_buys_discount->textsize(16);
+      db_totals_overview_buys_discount->align((FL_ALIGN_LEFT));
+      db_totals_overview_buys_discount->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "buys_discount", db_totals_overview_buys_discount);
+    } // Fl_Float_Input_Fmt* db_totals_overview_buys_discount
+    { db_totals_overview_buys_tax1 = new Fl_Float_Input_Fmt(415, 375, 110, 25, _tr("Buys Tax1"));
+      db_totals_overview_buys_tax1->type(1);
+      db_totals_overview_buys_tax1->box(FL_DOWN_BOX);
+      db_totals_overview_buys_tax1->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_buys_tax1->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_buys_tax1->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_buys_tax1->labelfont(0);
+      db_totals_overview_buys_tax1->labelsize(16);
+      db_totals_overview_buys_tax1->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_buys_tax1->textsize(16);
+      db_totals_overview_buys_tax1->align((FL_ALIGN_LEFT));
+      db_totals_overview_buys_tax1->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "buys_tax1", db_totals_overview_buys_tax1);
+    } // Fl_Float_Input_Fmt* db_totals_overview_buys_tax1
+    { db_totals_overview_buys_tax2 = new Fl_Float_Input_Fmt(415, 410, 110, 25, _tr("Buys Tax2"));
+      db_totals_overview_buys_tax2->type(1);
+      db_totals_overview_buys_tax2->box(FL_DOWN_BOX);
+      db_totals_overview_buys_tax2->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_buys_tax2->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_buys_tax2->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_buys_tax2->labelfont(0);
+      db_totals_overview_buys_tax2->labelsize(16);
+      db_totals_overview_buys_tax2->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_buys_tax2->textsize(16);
+      db_totals_overview_buys_tax2->align((FL_ALIGN_LEFT));
+      db_totals_overview_buys_tax2->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "buys_tax2", db_totals_overview_buys_tax2);
+    } // Fl_Float_Input_Fmt* db_totals_overview_buys_tax2
+    { db_totals_overview_buys_paid = new Fl_Float_Input_Fmt(415, 445, 110, 25, _tr("Buys Paid"));
+      db_totals_overview_buys_paid->type(1);
+      db_totals_overview_buys_paid->box(FL_DOWN_BOX);
+      db_totals_overview_buys_paid->color(FL_BACKGROUND2_COLOR);
+      db_totals_overview_buys_paid->selection_color(FL_SELECTION_COLOR);
+      db_totals_overview_buys_paid->labeltype(FL_NORMAL_LABEL);
+      db_totals_overview_buys_paid->labelfont(0);
+      db_totals_overview_buys_paid->labelsize(16);
+      db_totals_overview_buys_paid->labelcolor(FL_FOREGROUND_COLOR);
+      db_totals_overview_buys_paid->textsize(16);
+      db_totals_overview_buys_paid->align((FL_ALIGN_LEFT));
+      db_totals_overview_buys_paid->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("totals_overview", "buys_paid", db_totals_overview_buys_paid);
+    } // Fl_Float_Input_Fmt* db_totals_overview_buys_paid
+    tabTotals->end();
+  } // Fl_Group* tabTotals
+  tabs->end();
+  Fl_Group.current()->resizable(tabs);
+} // Fl_Tabs* tabs
+db_orders_order_type_id->textfont(db_orders_order_type_id->labelfont());
+db_orders_order_type_id->textsize(db_orders_order_type_id->labelsize());
+end();
+}
+
+function cb_Wrap(){}
+function cb_Wrap1(){}
+function cb_Wrap2(){}
+}

+ 775 - 0
ourbiz/edit-product-window.nut

@@ -0,0 +1,775 @@
+class Fl_Data_Table extends Flv_Table {
+	_forPrint = null;
+	
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+		_forPrint=false;
+	}
+}
+
+class Flu_Tree_Browser extends Flv_Table {
+	_forPrint = null;
+	
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+		_forPrint=false;
+	}
+}
+
+
+class Fl_Box_ClearLabel extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Flu_Combo_List extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Image_Box extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+class Fl_Choice_Int extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Float_Input_Fmt extends Fl_Float_Input {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class My_Fl_Float_Input extends Fl_Float_Input {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+class My_Fl_Return_Button extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Choice_Str extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Flu_Combo_Box extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+function add_input_field_to_map(tbl, fldname, fld){
+}
+	
+//class EditProductWindow extends Fl_Group {
+class EditProductWindow extends MyBaseWindow {
+	db_products_id=null;
+	db_products_description_ro=null;
+	db_products_mdate=null;
+	db_products_cdate=null;
+	tabs=null;
+	tabMain=null;
+	db_products_reference_code=null;
+	db_products_supplier_code=null;
+	db_products_bar_code=null;
+	db_products_sell_description=null;
+	db_products_buy_description=null;
+	db_products_sell_price=null;
+	db_products_measure_unit_id=null;
+	db_products_sales_tax_id=null;
+	db_products_warranty_id=null;
+	db_products_sell_quantity_min=null;
+	db_products_units_by_package=null;
+	db_products_weight=null;
+	db_products_sell_without_stock=null;
+	db_products_is_active=null;
+	db_products_show_on_sales=null;
+	db_products_show_on_buys=null;
+	db_products_show_on_web=null;
+	db_products_show_price_on_web=null;
+	tabNotes=null;
+	db_products_sell_notes=null;
+	tabNotesSupplier=null;
+	db_products_buy_notes=null;
+	tabTags=null;
+	db_products_tags=null;
+	tabGroups=null;
+	btnImage=null;
+	db_products_quantity_onhand=null;
+	tabPrices=null;
+	db_products_buy_price=null;
+	db_products_buy_discount=null;
+	db_products_buy_other_costs=null;
+	db_products_sell_markup=null;
+	markup_to_discount=null;
+	db_products_sell_price_ro=null;
+	db_products_price_decimals=null;
+	btnSaveProrduct=null;
+	db_products_stock_min=null;
+	db_products_stock_max=null;
+	db_products_buy_quantity_min=null;
+	db_products_price_formula=null;
+	db_products_price_date=null;
+	productPrices=null;
+	tabKit=null;
+	tabChartStatistics=null;
+	tabHistory=null;
+	tabReports=null;
+	grpExportImport=null;
+	btnProductsExport=null;
+	btnProductsImport=null;
+	chkWithoutPrices=null;
+	chkWebOnly=null;
+	boxExportImportCount=null;
+	btnProductGroupsExport=null;
+	btnProductGroupsImport=null;
+	btnUpdateWeb=null;
+	grpPrintPriceList=null;
+	chkPriceListWithVAT=null;
+	chkPriceListSellOnWeb=null;
+	btnPrintPriceList=null;
+	chkPriceListSellSales=null;
+	chkPriceListSellPDF=null;
+	tabTotals=null;
+	db_products_quantity_quoted_sales=null;
+	db_products_quantity_ordered_sales=null;
+	db_products_quantity_delivered=null;
+	db_products_quantity_invoiced_sales=null;
+	db_products_quantity_lost=null;
+	db_products_quantity_quoted_buys=null;
+	db_products_quantity_ordered_buys=null;
+	db_products_quantity_received=null;
+	db_products_quantity_invoiced_buys=null;
+	dbAction=null;
+	btnDbAction=null;
+	db_products_group_id=null;
+	
+constructor() {
+	base.constructor(10, 50, 800, 560, _tr("Edit Products"));
+begin();
+this->box(FL_FLAT_BOX);
+this->color(FL_BACKGROUND_COLOR);
+this->selection_color(FL_BACKGROUND_COLOR);
+this->labeltype(FL_NO_LABEL);
+this->labelfont(0);
+this->labelsize(14);
+this->labelcolor(FL_FOREGROUND_COLOR);
+this->align((FL_ALIGN_TOP));
+this->when(FL_WHEN_RELEASE);
+{ db_products_id =new Fl_Output(5, 5, 96, 25);
+  db_products_id->labeltype(FL_NO_LABEL);
+  db_products_id->labelsize(16);
+  db_products_id->textsize(16);
+  add_input_field_to_map("products", "id", db_products_id);
+} // Fl_Output* db_products_id
+{ db_products_description_ro =new Fl_Output(110, 5, 545, 25);
+  db_products_description_ro->labeltype(FL_NO_LABEL);
+  db_products_description_ro->labelsize(16);
+  db_products_description_ro->textsize(16);
+} // Fl_Output* db_products_description_ro
+{ db_products_mdate =new Fl_Output(666, 5, 130, 25);
+  db_products_mdate->labeltype(FL_NO_LABEL);
+  db_products_mdate->labelsize(16);
+  db_products_mdate->textsize(16);
+  add_input_field_to_map("products", "mdate", db_products_mdate);
+} // Fl_Output* db_products_mdate
+{ db_products_cdate =new Fl_Output(665, 35, 130, 25);
+  db_products_cdate->labeltype(FL_NO_LABEL);
+  db_products_cdate->labelsize(16);
+  db_products_cdate->textsize(16);
+  add_input_field_to_map("products", "cdate", db_products_cdate);
+} // Fl_Output* db_products_cdate
+{ tabs =new Fl_Tabs(5, 35, 790, 520);
+  tabs->selection_color(4);
+  tabs->labelsize(16);
+  tabs->labelcolor(FL_BACKGROUND2_COLOR);
+  { tabMain =new Fl_Group(5, 60, 790, 495, _tr("Main"));
+    tabMain->color(246);
+    tabMain->labelsize(16);
+    { db_products_reference_code =new Fl_Input(115, 70, 165, 25, _tr("Reference"));
+      db_products_reference_code->labelsize(16);
+      db_products_reference_code->textsize(16);
+      add_input_field_to_map("products", "reference_code", db_products_reference_code);
+    } // Fl_Input* db_products_reference_code
+    { db_products_supplier_code =new Fl_Input(380, 70, 165, 25, _tr("Ref. Supp."));
+      db_products_supplier_code->labelsize(16);
+      db_products_supplier_code->textsize(16);
+      add_input_field_to_map("products", "supplier_code", db_products_supplier_code);
+    } // Fl_Input* db_products_supplier_code
+    { db_products_bar_code =new Fl_Input(620, 70, 165, 25, _tr("Barcode"));
+      db_products_bar_code->labelsize(16);
+      db_products_bar_code->textsize(16);
+      add_input_field_to_map("products", "bar_code", db_products_bar_code);
+    } // Fl_Input* db_products_bar_code
+    { db_products_sell_description =new Fl_Input(115, 100, 670, 25, _tr("Description"));
+      db_products_sell_description->labelsize(16);
+      db_products_sell_description->textsize(16);
+      add_input_field_to_map("products", "sell_description", db_products_sell_description);
+    } // Fl_Input* db_products_sell_description
+    { db_products_buy_description =new Fl_Input(115, 130, 670, 25, _tr("Desc. Supp."));
+      db_products_buy_description->labelsize(16);
+      db_products_buy_description->textsize(16);
+      add_input_field_to_map("products", "buy_description", db_products_buy_description);
+    } // Fl_Input* db_products_buy_description
+    { db_products_sell_price =new Fl_Float_Input_Fmt(115, 160, 110, 25, _tr("Sales Price"));
+      db_products_sell_price->type(1);
+      db_products_sell_price->box(FL_DOWN_BOX);
+      db_products_sell_price->color(FL_BACKGROUND2_COLOR);
+      db_products_sell_price->selection_color(FL_SELECTION_COLOR);
+      db_products_sell_price->labeltype(FL_NORMAL_LABEL);
+      db_products_sell_price->labelfont(0);
+      db_products_sell_price->labelsize(16);
+      db_products_sell_price->labelcolor(FL_FOREGROUND_COLOR);
+      db_products_sell_price->textsize(16);
+      db_products_sell_price->align((FL_ALIGN_LEFT));
+      db_products_sell_price->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("products", "sell_price", db_products_sell_price);
+    } // Fl_Float_Input_Fmt* db_products_sell_price
+    { db_products_measure_unit_id =new Fl_Choice_Int(370, 160, 110, 25, _tr("Measure Unit"));
+      db_products_measure_unit_id->box(FL_FLAT_BOX);
+      db_products_measure_unit_id->down_box(FL_BORDER_BOX);
+      db_products_measure_unit_id->color(FL_BACKGROUND_COLOR);
+      db_products_measure_unit_id->selection_color(FL_SELECTION_COLOR);
+      db_products_measure_unit_id->labeltype(FL_NORMAL_LABEL);
+      db_products_measure_unit_id->labelfont(0);
+      db_products_measure_unit_id->labelsize(16);
+      db_products_measure_unit_id->labelcolor(FL_FOREGROUND_COLOR);
+      db_products_measure_unit_id->textsize(16);
+      db_products_measure_unit_id->align((FL_ALIGN_LEFT));
+      db_products_measure_unit_id->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("products", "measure_unit_id", db_products_measure_unit_id);
+    } // Fl_Choice_Int* db_products_measure_unit_id
+    { db_products_sales_tax_id =new Fl_Choice_Int(115, 190, 110, 25, _tr("V.A.T."));
+      db_products_sales_tax_id->box(FL_FLAT_BOX);
+      db_products_sales_tax_id->down_box(FL_BORDER_BOX);
+      db_products_sales_tax_id->color(FL_BACKGROUND_COLOR);
+      db_products_sales_tax_id->selection_color(FL_SELECTION_COLOR);
+      db_products_sales_tax_id->labeltype(FL_NORMAL_LABEL);
+      db_products_sales_tax_id->labelfont(0);
+      db_products_sales_tax_id->labelsize(16);
+      db_products_sales_tax_id->labelcolor(FL_FOREGROUND_COLOR);
+      db_products_sales_tax_id->textsize(16);
+      db_products_sales_tax_id->align((FL_ALIGN_LEFT));
+      db_products_sales_tax_id->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("products", "sales_tax_id", db_products_sales_tax_id);
+    } // Fl_Choice_Int* db_products_sales_tax_id
+    { db_products_warranty_id =new Fl_Choice_Int(370, 190, 110, 25, _tr("Warranty"));
+      db_products_warranty_id->box(FL_FLAT_BOX);
+      db_products_warranty_id->down_box(FL_BORDER_BOX);
+      db_products_warranty_id->color(FL_BACKGROUND_COLOR);
+      db_products_warranty_id->selection_color(FL_SELECTION_COLOR);
+      db_products_warranty_id->labeltype(FL_NORMAL_LABEL);
+      db_products_warranty_id->labelfont(0);
+      db_products_warranty_id->labelsize(16);
+      db_products_warranty_id->labelcolor(FL_FOREGROUND_COLOR);
+      db_products_warranty_id->textsize(16);
+      db_products_warranty_id->align((FL_ALIGN_LEFT));
+      db_products_warranty_id->when(FL_WHEN_RELEASE);
+      add_input_field_to_map("products", "warranty_id", db_products_warranty_id);
+    } // Fl_Choice_Int* db_products_warranty_id
+    { local o = db_products_sell_quantity_min =new Fl_Float_Input(370, 250, 110, 25, _tr("Sell Min. Qty."));
+      db_products_sell_quantity_min->type(1);
+      db_products_sell_quantity_min->labelsize(16);
+      db_products_sell_quantity_min->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "sell_quantity_min", db_products_sell_quantity_min);
+    } // Fl_Float_Input* db_products_sell_quantity_min
+    { local o = db_products_units_by_package =new Fl_Float_Input(370, 280, 110, 25, _tr("Units by Pack."));
+      db_products_units_by_package->type(1);
+      db_products_units_by_package->labelsize(16);
+      db_products_units_by_package->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "units_by_package", db_products_units_by_package);
+    } // Fl_Float_Input* db_products_units_by_package
+    { local o = db_products_weight =new Fl_Float_Input(370, 220, 110, 25, _tr("Weight"));
+      db_products_weight->type(1);
+      db_products_weight->labelsize(16);
+      db_products_weight->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "weight", db_products_weight);
+    } // Fl_Float_Input* db_products_weight
+    { db_products_sell_without_stock =new Fl_Check_Button(10, 250, 215, 25, _tr("Sell without stock"));
+      db_products_sell_without_stock->down_box(FL_DOWN_BOX);
+      db_products_sell_without_stock->labelsize(16);
+      add_input_field_to_map("products", "sell_without_stock", db_products_sell_without_stock);
+    } // Fl_Check_Button* db_products_sell_without_stock
+    { db_products_is_active =new Fl_Check_Button(10, 280, 110, 25, _tr("Active"));
+      db_products_is_active->down_box(FL_DOWN_BOX);
+      db_products_is_active->labelsize(16);
+      add_input_field_to_map("products", "is_active", db_products_is_active);
+    } // Fl_Check_Button* db_products_is_active
+    { db_products_show_on_sales =new Fl_Check_Button(10, 310, 105, 25, _tr("Sales"));
+      db_products_show_on_sales->down_box(FL_DOWN_BOX);
+      db_products_show_on_sales->labelsize(16);
+      add_input_field_to_map("products", "show_on_sales", db_products_show_on_sales);
+    } // Fl_Check_Button* db_products_show_on_sales
+    { db_products_show_on_buys =new Fl_Check_Button(10, 340, 95, 25, _tr("Buys"));
+      db_products_show_on_buys->down_box(FL_DOWN_BOX);
+      db_products_show_on_buys->labelsize(16);
+      add_input_field_to_map("products", "show_on_buys", db_products_show_on_buys);
+    } // Fl_Check_Button* db_products_show_on_buys
+    { db_products_show_on_web =new Fl_Check_Button(115, 310, 120, 25, _tr("Web"));
+      db_products_show_on_web->down_box(FL_DOWN_BOX);
+      db_products_show_on_web->labelsize(16);
+      add_input_field_to_map("products", "show_on_web", db_products_show_on_web);
+    } // Fl_Check_Button* db_products_show_on_web
+    { db_products_show_price_on_web =new Fl_Check_Button(115, 340, 100, 25, _tr("Web price"));
+      db_products_show_price_on_web->down_box(FL_DOWN_BOX);
+      db_products_show_price_on_web->labelsize(16);
+      add_input_field_to_map("products", "show_price_on_web", db_products_show_price_on_web);
+    } // Fl_Check_Button* db_products_show_price_on_web
+    { local o =new Fl_Group(675, 402, 110, 143);
+      { local o =new Fl_Box(675, 402, 110, 68, _tr("Spacer"));
+        o->labeltype(FL_NO_LABEL);
+        Fl_Group.current()->resizable(o);
+      } // Fl_Box* o
+      { dbAction = new Fl_Button(675, 520, 110, 25);
+        dbAction->label(_tr("Action"));
+        dbAction->down_box(FL_BORDER_BOX);
+        dbAction->labelsize(16);
+        dbAction->textsize(16);
+        dbAction->align((FL_ALIGN_TOP));
+      } // Fl_Choice* dbAction
+      { btnDbAction = new My_Fl_Return_Button(675, 470, 110, 25, _tr("Action"));
+        btnDbAction->labelsize(16);
+      } // Fl_Button* btnDbAction
+      o->end();
+    } // Fl_Group* o
+    { local o =new Fl_Tabs(10, 370, 650, 181);
+      o->selection_color(4);
+      o->labelsize(16);
+      o->labelcolor(FL_BACKGROUND2_COLOR);
+      { tabNotes =new Fl_Group(10, 400, 650, 150, _tr("Notes"));
+        tabNotes->labelsize(16);
+        { db_products_sell_notes =new Fl_Text_Editor_Buffered(10, 400, 650, 150);
+          db_products_sell_notes->type(4);
+          db_products_sell_notes->box(FL_DOWN_BOX);
+          db_products_sell_notes->color(FL_BACKGROUND2_COLOR);
+          db_products_sell_notes->selection_color(FL_SELECTION_COLOR);
+          db_products_sell_notes->labeltype(FL_NO_LABEL);
+          db_products_sell_notes->labelfont(0);
+          db_products_sell_notes->labelsize(16);
+          db_products_sell_notes->labelcolor(FL_FOREGROUND_COLOR);
+          db_products_sell_notes->textsize(16);
+          db_products_sell_notes->align((FL_ALIGN_TOP_LEFT));
+          db_products_sell_notes->when(FL_WHEN_RELEASE);
+          Fl_Group.current()->resizable(db_products_sell_notes);
+          add_input_field_to_map("products", "sell_notes", db_products_sell_notes);
+        } // Fl_Text_Editor_Buffered* db_products_sell_notes
+        tabNotes->end();
+      } // Fl_Group* tabNotes
+      { tabNotesSupplier =new Fl_Group(10, 400, 650, 150, _tr("Notes Supplier"));
+        tabNotesSupplier->labelsize(16);
+        tabNotesSupplier->hide();
+        { db_products_buy_notes =new Fl_Text_Editor_Buffered(10, 400, 650, 150);
+          db_products_buy_notes->type(4);
+          db_products_buy_notes->box(FL_DOWN_BOX);
+          db_products_buy_notes->color(FL_BACKGROUND2_COLOR);
+          db_products_buy_notes->selection_color(FL_SELECTION_COLOR);
+          db_products_buy_notes->labeltype(FL_NO_LABEL);
+          db_products_buy_notes->labelfont(0);
+          db_products_buy_notes->labelsize(16);
+          db_products_buy_notes->labelcolor(FL_FOREGROUND_COLOR);
+          db_products_buy_notes->textsize(16);
+          db_products_buy_notes->align((FL_ALIGN_TOP_LEFT));
+          db_products_buy_notes->when(FL_WHEN_RELEASE);
+          Fl_Group.current()->resizable(db_products_buy_notes);
+          add_input_field_to_map("products", "buy_notes", db_products_buy_notes);
+        } // Fl_Text_Editor_Buffered* db_products_buy_notes
+        tabNotesSupplier->end();
+      } // Fl_Group* tabNotesSupplier
+      { tabTags =new Fl_Group(10, 400, 650, 150, _tr("Tags"));
+        tabTags->labelsize(16);
+        tabTags->hide();
+        { db_products_tags =new Fl_Text_Editor_Buffered(10, 400, 650, 150);
+          db_products_tags->type(4);
+          db_products_tags->box(FL_DOWN_BOX);
+          db_products_tags->color(FL_BACKGROUND2_COLOR);
+          db_products_tags->selection_color(FL_SELECTION_COLOR);
+          db_products_tags->labeltype(FL_NO_LABEL);
+          db_products_tags->labelfont(0);
+          db_products_tags->labelsize(16);
+          db_products_tags->labelcolor(FL_FOREGROUND_COLOR);
+          db_products_tags->textsize(16);
+          db_products_tags->align((FL_ALIGN_TOP_LEFT));
+          db_products_tags->when(FL_WHEN_RELEASE);
+          Fl_Group.current()->resizable(db_products_tags);
+          add_input_field_to_map("products", "tags", db_products_tags);
+        } // Fl_Text_Editor_Buffered* db_products_tags
+        tabTags->end();
+      } // Fl_Group* tabTags
+      { tabGroups =new Fl_Group(10, 395, 650, 156, _tr("Groups"));
+        tabGroups->hide();
+        { db_products_group_id = new Flu_Tree_Browser(10, 400, 650, 150);
+          db_products_group_id->box(FL_DOWN_BOX);
+          db_products_group_id->color(FL_BACKGROUND2_COLOR);
+          db_products_group_id->selection_color(FL_SELECTION_COLOR);
+          db_products_group_id->labeltype(FL_NORMAL_LABEL);
+          db_products_group_id->labelfont(0);
+          db_products_group_id->labelsize(16);
+          db_products_group_id->labelcolor(FL_FOREGROUND_COLOR);
+          db_products_group_id->align((FL_ALIGN_TOP));
+          db_products_group_id->when(FL_WHEN_CHANGED);
+          add_input_field_to_map("products", "group_id", db_products_group_id);
+        } // Flu_Tree_Browser* db_products_group_id
+        tabGroups->end();
+      } // Fl_Group* tabGroups
+      o->end();
+    } // Fl_Tabs* o
+    { btnImage =new Fl_Image_Box(485, 158, 300, 232);
+      btnImage->box(FL_ENGRAVED_BOX);
+      btnImage->color(FL_BACKGROUND2_COLOR);
+      btnImage->selection_color(FL_BACKGROUND_COLOR);
+      btnImage->labeltype(FL_NORMAL_LABEL);
+      btnImage->labelfont(0);
+      btnImage->labelsize(14);
+      btnImage->labelcolor(FL_FOREGROUND_COLOR);
+      btnImage->align((FL_ALIGN_CLIP|FL_ALIGN_INSIDE));
+      btnImage->when(FL_WHEN_RELEASE);
+    } // Fl_Image_Box* btnImage
+    { local o =new Fl_Check_Button(370, 375, 102, 25, _tr("Wrap lines"));
+      o->down_box(FL_DOWN_BOX);
+      o->value(1);
+      o->labelsize(16);
+      o->callback(cb_Wrap);
+    } // Fl_Check_Button* o
+    { local o = db_products_quantity_onhand =new Fl_Float_Input(115, 220, 110, 25, _tr("Onhand"));
+      db_products_quantity_onhand->type(1);
+      db_products_quantity_onhand->labelsize(16);
+      db_products_quantity_onhand->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_onhand", db_products_quantity_onhand);
+    } // Fl_Float_Input* db_products_quantity_onhand
+    tabMain->end();
+    Fl_Group.current()->resizable(tabMain);
+  } // Fl_Group* tabMain
+  { tabPrices =new Fl_Group(5, 60, 790, 495, _tr("Prices"));
+    tabPrices->color(246);
+    tabPrices->labelsize(16);
+    tabPrices->hide();
+    { local o =new Fl_Group(15, 88, 770, 201, _tr("Sales Price"));
+      o->box(FL_UP_BOX);
+      o->color(166);
+      o->labelsize(16);
+      { db_products_buy_price =new Fl_Float_Input_Fmt(25, 115, 115, 25, _tr("Buy $"));
+        db_products_buy_price->type(1);
+        db_products_buy_price->box(FL_DOWN_BOX);
+        db_products_buy_price->color(FL_BACKGROUND2_COLOR);
+        db_products_buy_price->selection_color(FL_SELECTION_COLOR);
+        db_products_buy_price->labeltype(FL_NORMAL_LABEL);
+        db_products_buy_price->labelfont(0);
+        db_products_buy_price->labelsize(16);
+        db_products_buy_price->labelcolor(FL_FOREGROUND_COLOR);
+        db_products_buy_price->textsize(16);
+        db_products_buy_price->align((FL_ALIGN_TOP_LEFT));
+        db_products_buy_price->when(FL_WHEN_RELEASE);
+        add_input_field_to_map("products", "buy_price", db_products_buy_price);
+      } // Fl_Float_Input_Fmt* db_products_buy_price
+      { local o = db_products_buy_discount =new Fl_Float_Input_Fmt(151, 115, 115, 25, _tr("Buy Disc. %"));
+        db_products_buy_discount->type(1);
+        db_products_buy_discount->box(FL_DOWN_BOX);
+        db_products_buy_discount->color(FL_BACKGROUND2_COLOR);
+        db_products_buy_discount->selection_color(FL_SELECTION_COLOR);
+        db_products_buy_discount->labeltype(FL_NORMAL_LABEL);
+        db_products_buy_discount->labelfont(0);
+        db_products_buy_discount->labelsize(16);
+        db_products_buy_discount->labelcolor(FL_FOREGROUND_COLOR);
+        db_products_buy_discount->textsize(16);
+        db_products_buy_discount->align((FL_ALIGN_TOP_LEFT));
+        db_products_buy_discount->when(FL_WHEN_RELEASE);
+        add_input_field_to_map("products", "buy_discount", db_products_buy_discount);
+        o->decimal_places(-6);
+      } // Fl_Float_Input_Fmt* db_products_buy_discount
+      { db_products_buy_other_costs =new Fl_Float_Input_Fmt(278, 115, 115, 25, _tr("Other Costs $"));
+        db_products_buy_other_costs->type(1);
+        db_products_buy_other_costs->box(FL_DOWN_BOX);
+        db_products_buy_other_costs->color(FL_BACKGROUND2_COLOR);
+        db_products_buy_other_costs->selection_color(FL_SELECTION_COLOR);
+        db_products_buy_other_costs->labeltype(FL_NORMAL_LABEL);
+        db_products_buy_other_costs->labelfont(0);
+        db_products_buy_other_costs->labelsize(16);
+        db_products_buy_other_costs->labelcolor(FL_FOREGROUND_COLOR);
+        db_products_buy_other_costs->textsize(16);
+        db_products_buy_other_costs->align((FL_ALIGN_TOP_LEFT));
+        db_products_buy_other_costs->when(FL_WHEN_RELEASE);
+        add_input_field_to_map("products", "buy_other_costs", db_products_buy_other_costs);
+      } // Fl_Float_Input_Fmt* db_products_buy_other_costs
+      { local o = db_products_sell_markup =new Fl_Float_Input_Fmt(404, 115, 115, 25, _tr("Markup %"));
+        db_products_sell_markup->type(1);
+        db_products_sell_markup->box(FL_DOWN_BOX);
+        db_products_sell_markup->color(FL_BACKGROUND2_COLOR);
+        db_products_sell_markup->selection_color(FL_SELECTION_COLOR);
+        db_products_sell_markup->labeltype(FL_NORMAL_LABEL);
+        db_products_sell_markup->labelfont(0);
+        db_products_sell_markup->labelsize(16);
+        db_products_sell_markup->labelcolor(FL_FOREGROUND_COLOR);
+        db_products_sell_markup->textsize(16);
+        db_products_sell_markup->align((FL_ALIGN_TOP_LEFT));
+        db_products_sell_markup->when(FL_WHEN_RELEASE);
+        add_input_field_to_map("products", "sell_markup", db_products_sell_markup);
+        //o->decimal_places(-6);
+      } // Fl_Float_Input_Fmt* db_products_sell_markup
+      { local o = markup_to_discount =new Fl_Float_Input_Fmt(531, 115, 115, 25, _tr("Margin %"));
+        markup_to_discount->type(1);
+        markup_to_discount->box(FL_DOWN_BOX);
+        markup_to_discount->color(FL_BACKGROUND2_COLOR);
+        markup_to_discount->selection_color(FL_SELECTION_COLOR);
+        markup_to_discount->labeltype(FL_NORMAL_LABEL);
+        markup_to_discount->labelfont(0);
+        markup_to_discount->labelsize(16);
+        markup_to_discount->labelcolor(FL_FOREGROUND_COLOR);
+        markup_to_discount->textsize(16);
+        markup_to_discount->align((FL_ALIGN_TOP_LEFT));
+        markup_to_discount->when(FL_WHEN_RELEASE);
+        //o->decimal_places(-6);
+      } // Fl_Float_Input_Fmt* markup_to_discount
+      { db_products_sell_price_ro =new Fl_Float_Input_Fmt(658, 115, 115, 25, _tr("Sales $"));
+        db_products_sell_price_ro->type(1);
+        db_products_sell_price_ro->box(FL_DOWN_BOX);
+        db_products_sell_price_ro->color(FL_BACKGROUND2_COLOR);
+        db_products_sell_price_ro->selection_color(FL_SELECTION_COLOR);
+        db_products_sell_price_ro->labeltype(FL_NORMAL_LABEL);
+        db_products_sell_price_ro->labelfont(0);
+        db_products_sell_price_ro->labelsize(16);
+        db_products_sell_price_ro->labelcolor(FL_FOREGROUND_COLOR);
+        db_products_sell_price_ro->textsize(16);
+        db_products_sell_price_ro->align((FL_ALIGN_TOP_LEFT));
+        db_products_sell_price_ro->when(FL_WHEN_RELEASE);
+      } // Fl_Float_Input_Fmt* db_products_sell_price_ro
+      { local o = db_products_price_decimals =new Fl_Int_Input(530, 150, 30, 25, _tr("Decimals for calculation"));
+        db_products_price_decimals->type(2);
+        db_products_price_decimals->labelfont(1);
+        db_products_price_decimals->labelsize(16);
+        db_products_price_decimals->textfont(1);
+        db_products_price_decimals->textsize(16);
+        add_input_field_to_map("products", "price_decimals", db_products_price_decimals);
+        //o->decimal_places(-6);
+      } // Fl_Int_Input* db_products_price_decimals
+      { btnSaveProrduct =new Fl_Button(662, 150, 111, 25, _tr("Save"));
+        btnSaveProrduct->labelsize(16);
+      } // Fl_Button* btnSaveProrduct
+      { local o = db_products_stock_min =new Fl_Float_Input(665, 195, 110, 25, _tr("Stock Min."));
+        db_products_stock_min->type(1);
+        db_products_stock_min->labelsize(16);
+        db_products_stock_min->textsize(16);
+        add_input_field_to_map("products", "stock_min", db_products_stock_min);
+        o->decimal_places(-6);
+      } // Fl_Float_Input* db_products_stock_min
+      { local o = db_products_stock_max =new Fl_Float_Input(665, 225, 110, 25, _tr("Stock Max."));
+        db_products_stock_max->type(1);
+        db_products_stock_max->labelsize(16);
+        db_products_stock_max->textsize(16);
+        add_input_field_to_map("products", "stock_max", db_products_stock_max);
+        o->decimal_places(-6);
+      } // Fl_Float_Input* db_products_stock_max
+      { local o = db_products_buy_quantity_min =new Fl_Float_Input(665, 255, 110, 25, _tr("Buy Min. Qty."));
+        db_products_buy_quantity_min->type(1);
+        db_products_buy_quantity_min->labelsize(16);
+        db_products_buy_quantity_min->textsize(16);
+        add_input_field_to_map("products", "buy_quantity_min", db_products_buy_quantity_min);
+        o->decimal_places(-6);
+      } // Fl_Float_Input* db_products_buy_quantity_min
+      { db_products_price_formula =new Fl_Input(25, 197, 495, 83, _tr("Price formula"));
+        db_products_price_formula->type(4);
+        db_products_price_formula->labelsize(16);
+        db_products_price_formula->textsize(16);
+        db_products_price_formula->align((FL_ALIGN_TOP_LEFT));
+        add_input_field_to_map("products", "price_formula", db_products_price_formula);
+      } // Fl_Input* db_products_price_formula
+      { db_products_price_date =new Fl_Output(25, 150, 130, 25, _tr("Last Update"));
+        db_products_price_date->labelsize(16);
+        db_products_price_date->textsize(16);
+        db_products_price_date->align((FL_ALIGN_RIGHT));
+      } // Fl_Output* db_products_price_date
+      o->end();
+    } // Fl_Group* o
+    { local o =new Fl_Box(15, 290, 770, 40, _tr("Spacer"));
+      o->labeltype(FL_NO_LABEL);
+      Fl_Group.current()->resizable(o);
+    } // Fl_Box* o
+    { productPrices =new Fl_Group(15, 332, 770, 212);
+      productPrices->box(FL_UP_BOX);
+      productPrices->color(166);
+      productPrices->labeltype(FL_NO_LABEL);
+      productPrices->labelsize(16);
+      productPrices->end();
+    } // Fl_Group* productPrices
+    tabPrices->end();
+  } // Fl_Group* tabPrices
+  { tabKit =new Fl_Group(5, 59, 790, 495, _tr("Kit"));
+    tabKit->color(246);
+    tabKit->labelsize(16);
+    tabKit->hide();
+    tabKit->end();
+  } // Fl_Group* tabKit
+  { tabChartStatistics =new Fl_Group(5, 60, 790, 495, _tr("Statistics"));
+    tabChartStatistics->color(246);
+    tabChartStatistics->labelsize(16);
+    tabChartStatistics->hide();
+    tabChartStatistics->end();
+  } // Fl_Group* tabChartStatistics
+  { tabHistory =new Fl_Group(5, 60, 790, 495, _tr("History"));
+    tabHistory->color(246);
+    tabHistory->labelsize(16);
+    tabHistory->hide();
+    tabHistory->end();
+  } // Fl_Group* tabHistory
+  { tabReports =new Fl_Group(5, 60, 790, 495, _tr("Reports"));
+    tabReports->box(FL_UP_BOX);
+    tabReports->color(246);
+    tabReports->labelsize(16);
+    tabReports->hide();
+    { grpExportImport =new Fl_Group(15, 465, 770, 80, _tr("Export / Import"));
+      grpExportImport->box(FL_ENGRAVED_FRAME);
+      grpExportImport->labelsize(16);
+      { btnProductsExport =new Fl_Button(25, 475, 175, 25, _tr("Products Export"));
+        btnProductsExport->labelsize(16);
+      } // Fl_Button* btnProductsExport
+      { btnProductsImport =new Fl_Button(25, 510, 175, 25, _tr("Products Import"));
+        btnProductsImport->labelsize(16);
+      } // Fl_Button* btnProductsImport
+      { chkWithoutPrices =new Fl_Check_Button(225, 480, 150, 25, _tr("Withouth Prices"));
+        chkWithoutPrices->down_box(FL_DOWN_BOX);
+        chkWithoutPrices->labelsize(16);
+      } // Fl_Check_Button* chkWithoutPrices
+      { chkWebOnly =new Fl_Check_Button(225, 510, 150, 25, _tr("WEB Only"));
+        chkWebOnly->down_box(FL_DOWN_BOX);
+        chkWebOnly->labelsize(16);
+      } // Fl_Check_Button* chkWebOnly
+      { boxExportImportCount =new Fl_Box(405, 499, 42, 25, _tr("0"));
+        boxExportImportCount->labelsize(16);
+      } // Fl_Box* boxExportImportCount
+      { btnProductGroupsExport =new Fl_Button(555, 475, 220, 25, _tr("Product Groups Export"));
+        btnProductGroupsExport->labelsize(16);
+      } // Fl_Button* btnProductGroupsExport
+      { btnProductGroupsImport =new Fl_Button(555, 510, 220, 25, _tr("Product Groups import"));
+        btnProductGroupsImport->labelsize(16);
+      } // Fl_Button* btnProductGroupsImport
+      grpExportImport->end();
+    } // Fl_Group* grpExportImport
+    { btnUpdateWeb =new Fl_Button(610, 70, 175, 25, _tr("Update WEB"));
+      btnUpdateWeb->labelsize(16);
+    } // Fl_Button* btnUpdateWeb
+    { grpPrintPriceList =new Fl_Group(10, 85, 195, 165, _tr("Price List"));
+      grpPrintPriceList->box(FL_ENGRAVED_FRAME);
+      grpPrintPriceList->labelsize(16);
+      { chkPriceListWithVAT =new Fl_Check_Button(20, 95, 175, 25, _tr("With V.A.T."));
+        chkPriceListWithVAT->down_box(FL_DOWN_BOX);
+        chkPriceListWithVAT->labelsize(16);
+      } // Fl_Check_Button* chkPriceListWithVAT
+      { chkPriceListSellOnWeb =new Fl_Check_Button(20, 125, 170, 25, _tr("Sell on WEB"));
+        chkPriceListSellOnWeb->down_box(FL_DOWN_BOX);
+        chkPriceListSellOnWeb->labelsize(16);
+      } // Fl_Check_Button* chkPriceListSellOnWeb
+      { btnPrintPriceList =new Fl_Button(20, 215, 175, 25, _tr("Print"));
+        btnPrintPriceList->labelsize(16);
+      } // Fl_Button* btnPrintPriceList
+      { chkPriceListSellSales =new Fl_Check_Button(20, 155, 175, 25, _tr("Sales"));
+        chkPriceListSellSales->down_box(FL_DOWN_BOX);
+        chkPriceListSellSales->labelsize(16);
+      } // Fl_Check_Button* chkPriceListSellSales
+      { chkPriceListSellPDF =new Fl_Check_Button(20, 185, 175, 25, _tr("PDF"));
+        chkPriceListSellPDF->down_box(FL_DOWN_BOX);
+        chkPriceListSellPDF->labelsize(16);
+      } // Fl_Check_Button* chkPriceListSellPDF
+      grpPrintPriceList->end();
+    } // Fl_Group* grpPrintPriceList
+    tabReports->end();
+  } // Fl_Group* tabReports
+  { tabTotals =new Fl_Group(5, 60, 790, 495, _tr("Totals"));
+    tabTotals->color(246);
+    tabTotals->labelsize(16);
+    tabTotals->hide();
+    { local o = db_products_quantity_quoted_sales =new Fl_Float_Input(220, 80, 110, 25, _tr("Quantity quoted sales"));
+      db_products_quantity_quoted_sales->type(1);
+      db_products_quantity_quoted_sales->labelsize(16);
+      db_products_quantity_quoted_sales->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_quoted_sales", db_products_quantity_quoted_sales);
+    } // Fl_Float_Input* db_products_quantity_quoted_sales
+    { local o = db_products_quantity_ordered_sales =new Fl_Float_Input(220, 115, 110, 25, _tr("Quantity ordered sales"));
+      db_products_quantity_ordered_sales->type(1);
+      db_products_quantity_ordered_sales->labelsize(16);
+      db_products_quantity_ordered_sales->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_ordered_sales", db_products_quantity_ordered_sales);
+    } // Fl_Float_Input* db_products_quantity_ordered_sales
+    { local o = db_products_quantity_delivered =new Fl_Float_Input(220, 150, 110, 25, _tr("Quantity delivered"));
+      db_products_quantity_delivered->type(1);
+      db_products_quantity_delivered->labelsize(16);
+      db_products_quantity_delivered->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_delivered", db_products_quantity_delivered);
+    } // Fl_Float_Input* db_products_quantity_delivered
+    { local o = db_products_quantity_invoiced_sales =new Fl_Float_Input(220, 185, 110, 25, _tr("Quantity invoiced sales"));
+      db_products_quantity_invoiced_sales->type(1);
+      db_products_quantity_invoiced_sales->labelsize(16);
+      db_products_quantity_invoiced_sales->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_invoiced_sales", db_products_quantity_invoiced_sales);
+    } // Fl_Float_Input* db_products_quantity_invoiced_sales
+    { local o = db_products_quantity_lost =new Fl_Float_Input(220, 220, 110, 25, _tr("Quantity lost"));
+      db_products_quantity_lost->type(1);
+      db_products_quantity_lost->labelsize(16);
+      db_products_quantity_lost->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_lost", db_products_quantity_lost);
+    } // Fl_Float_Input* db_products_quantity_lost
+    { local o = db_products_quantity_quoted_buys =new Fl_Float_Input(665, 85, 110, 25, _tr("Quantity quoted buys"));
+      db_products_quantity_quoted_buys->type(1);
+      db_products_quantity_quoted_buys->labelsize(16);
+      db_products_quantity_quoted_buys->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_quoted_buys", db_products_quantity_quoted_buys);
+    } // Fl_Float_Input* db_products_quantity_quoted_buys
+    { local o = db_products_quantity_ordered_buys =new Fl_Float_Input(665, 120, 110, 25, _tr("Quantity ordered buys"));
+      db_products_quantity_ordered_buys->type(1);
+      db_products_quantity_ordered_buys->labelsize(16);
+      db_products_quantity_ordered_buys->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_ordered_buys", db_products_quantity_ordered_buys);
+    } // Fl_Float_Input* db_products_quantity_ordered_buys
+    { local o = db_products_quantity_received =new Fl_Float_Input(665, 155, 110, 25, _tr("Quantity received"));
+      db_products_quantity_received->type(1);
+      db_products_quantity_received->labelsize(16);
+      db_products_quantity_received->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_received", db_products_quantity_received);
+    } // Fl_Float_Input* db_products_quantity_received
+    { local o = db_products_quantity_invoiced_buys =new Fl_Float_Input(665, 190, 110, 25, _tr("Quantity invoiced buys"));
+      db_products_quantity_invoiced_buys->type(1);
+      db_products_quantity_invoiced_buys->labelsize(16);
+      db_products_quantity_invoiced_buys->textsize(16);
+      o->decimal_places(-6);
+      add_input_field_to_map("products", "quantity_invoiced_buys", db_products_quantity_invoiced_buys);
+    } // Fl_Float_Input* db_products_quantity_invoiced_buys
+    tabTotals->end();
+  } // Fl_Group* tabTotals
+  tabs->end();
+  Fl_Group.current()->resizable(tabs);
+} // Fl_Tabs* tabs
+end();
+}
+
+function cb_Wrap(){}
+function cb_btnSearch(){}
+function cb_btnSelect(){}
+function cb_btnUpdate(){}
+function cb_btnInsert(){}
+}

+ 672 - 0
ourbiz/fluid2SquiLu.nut

@@ -0,0 +1,672 @@
+// squilu generator from FLUID project
+// Usage:  
+//   squilu  fluid2SquiLu.nut  input.fl  [output.nut]
+//
+//translated to SquiLu (http://code.google.com/p/squilu) by Domingo Alvarez Duarte
+//
+
+// murgaLua generator from FLUID project
+// Usage:  
+//   murgaLua  lua_from_fluid.lua  input.fl  [output.lua]
+
+// Copyright (c) 2008 Patrick Rapin by Olivetti Engineering SA
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// Configuration variables. Change the fields of the configuration table to 
+// match your preferences. You can also override them on the command line.
+local default_configuration = {
+	// If "shebang" is defined as a file path to the Lua interpreter, a Unix shebang will
+	// be added at top of the file. If the string contains backslashes or end in .exe,
+	// a batch header is added to turn the script into a valid Windows .BAT file.
+	shebang = null,
+	
+	// Indentation parameter. If it is a number, that number of spaces will be used 
+	// for each level. If it is a string, it is places once for each level.
+	indentation = 2,
+	
+	// Current widget variable name. FLUID normally uses "o" when generating code.
+	currentvar = "o",
+	
+	// Internationalization text function. If defined to a function name, every 
+	// text label will be passed to that function. If not defined, the parameter in
+	// "Project Settings... Internationalization... GNU gettext... Function" will be used.
+	textfilter = "_tr",
+	
+	// If set to "syntax", the syntax of the generated file is checked at the end.
+	// If set to "run", the generated script is run
+	check = "none",
+}
+
+// Global variables
+local Grammar, source_file, configuration;
+// Forward declaration of functions
+//local DecodeOption, ReadFile, BuildGrammar, GetItem, ParseItem, ParseGroup, ParseAttributes;
+// Table of functions for rendering
+local Write = {}, FindMembers = {};
+// Functions to output data into a file or stdout
+local Output, Output2;// OpenOutput, WriteScript, WriteVariables, GetAccessMode;
+
+// In this function are concentrated most of the bugs... The list try to enumerate all
+// 
+function BuildGrammar(){
+	local fields = { name = "string", body = "group", attr = "widget"  };
+	local types = [ [ "name", "attr" ], [ "name", "attr", "body" ], [ "name" ] ];
+	local list1 = [  "comment", "code", "decl", "MenuItem", "Fl_" ];
+	local list2 = [ "class", "codeblock", "declblock", "Fl_Window", "Fl_Group", "widget_class",
+		"Fl_Choice", "Fl_Input_Choice", "Submenu", "Function", "Fl_Scroll", "Fl_Menu_Bar", 
+		"Fl_Tabs", "Fl_Menu_Button", "Fl_Wizard", "Fl_Pack", "Fl_Tile", "Fl_Table", "Fl_Tree" ];
+	local list3 = [ "version", "header_name", "code_name", "gridx", "gridy", "snap", 
+		"i18n_type", "i18n_include", "i18n_function", "i18n_file", "i18n_set" ];
+	local str_methods = [ "tooltip", "type", "box", "down_box", "xclass", "labeltype" ];
+	local str_ext_methods = [ "label", "callback", "after", "image", "user_data", "class",
+		"code0", "code1", "code2", "code3", ":" ];
+	local number_methods = [ "labelsize", "align", "value", "textcolor", "selection_color",
+		"labelcolor", "color", "labelfont", "textfont", "when", "textsize", "step", 
+		"maximum", "minimum", "shortcut" ];
+	local img_list = [ "GIF", "BMP", "JPEG", "XBM", "XPM", "PNG" ];
+	local composed_list = [ "Fl_Window", "Fl_Browser", "Fl_Input", "Fl_Output" ];
+	local group_list = [ "Fl_Group", "Fl_Browser", "Fl_Color_Chooser", "Fl_Help_View", 
+		"Fl_Input_Choice", "Fl_Pack", "Fl_Scroll", "Fl_Tabs", "Fl_Spinner", 
+		"Fl_Text_Display", "Fl_Tile", "Fl_Window", "Fl_Wizard" ];
+	local images = { BM="BMP", PPM="PNM", PGM="PNM", PBM="PNM", JPG="JPEG" };
+	local FLUID = {Normal=0, Vertical=0, Dot=0, Integer=0, normal=0, No_Select=0, BOTH=0, 
+		Toggle=1, Horizontal=1, Simple=1, Line=1, Float=1, popup1=1, Select=1, HORIZONTAL=1, Vert_Fill=2,
+		Fill=2, Int=2, popup2=2, Hold=2, VERTICAL=2, Horz_Fill=3, popup3=3, Multi=3,
+		Vert_Knob=4, Multiline=4, popup12=4, Horz_Knob=5, Secret=5, popup23=5, Radio=102,
+		HORIZONTAL_ALWAYS=5, popup13=6, VERTICAL_ALWAYS=6, popup123=7, BOTH_ALWAYS=7,
+		["Vert Fill"]=2, ["Horz Fill"]=3, ["Vert Knob"]=4, ["Horz Knob"]=5 };
+	local menu_const = { Toggle = 2, Radio = 8, divider=128, deactivate=1, hide=16 };
+	local attr = { xywh = "list", size_range = "list" };
+	local methods = {}, composed = {}, groups = {};
+	local grammar = { attr = attr, konst = FLUID, images = images, groups = groups,
+		methods = methods, composed = composed, menu_const = menu_const };
+	
+	foreach( k,v in fields) fields[k] = [ k, v ];
+	foreach(i in types) for(local j=0, len = i.len(); j < len; ++j) i[j] = fields[i[j]];
+	foreach(k in list1) grammar[k] <- types[0];
+	foreach(k in list2) grammar[k] <- types[1];
+	foreach(k in list3) grammar[k] <- types[2];
+	foreach(k in str_methods) attr[k] <- "string";
+	foreach(k in str_ext_methods) attr[k] <- "string";
+	foreach(k in number_methods) attr[k] <- "integer";
+	foreach(k in img_list) images[k] <- k;
+	foreach(k in str_methods) methods[k] <- true;
+	foreach(k in number_methods) methods[k] <- true;
+	foreach(k in composed_list) composed[k] <- true;
+	foreach(k in group_list) groups[k] <- true;
+	return grammar;
+}
+
+function ReadFile(filename){
+	local fd = file(filename, "rt");
+	local data = fd.read(fd.len());
+	fd.close();
+	// Replace escaped characters to simplify parsing
+	data = data.gsub("\\([^%d])", function(c) {return format("\\%03d", c[0]); return true; })
+	return data;
+}
+
+function GetItem(pos, type, parent=null){
+	local p1, p2, item;
+	source_file.find_lua("^%s*([%w_%.%-<>:]+)%s+", function(start, end, match){
+		p1 = start; p2 = end; item = match;
+	}, pos);
+	if (p1){ 
+		if (type == "integer") return [item.tointeger(), p2+1];
+		assert(type == "string");
+		return [item, p2+1];
+	}
+	p1 = null;
+	source_file.find_lua("^%s*(%b{})%s+", function(start, end, match){
+		p1 = start; p2 = end; item = match;
+	}, pos);
+	assert(p1);
+
+	local content = item.slice(1,-1);
+	if (type == "string") item = content.gsub("\\(%-?%d%d%d)", function(val) {return str_from_chars(val.tointeger());});
+	else if (type == "list"){
+		item = [];
+		content.gmatch("%-?%d+", function(k){
+			item.push(k.tointeger());
+			return true;
+		});
+	}
+	else if (type == "group") 	item = ParseGroup(pos+1, pos+content.len(), parent);
+	else if (type == "widget") item = ParseAttributes(pos+1, pos+content.len());
+	return [item, p2+1];
+}
+
+function ParseItem(pos, parent){
+	local rc, key, item = {};
+	rc = GetItem(pos, "string", item);
+	key = rc[0]; pos = rc[1]; 
+	item.key <- key;
+	local modes = Grammar.get(key, false);
+	if (!modes && key.match("Fl_")) modes = Grammar.Fl_;
+	assert(modes);
+	foreach(mode in modes){
+		local name = mode[0], type = mode[1];
+		rc = GetItem(pos, type, item);
+		key = rc[0]; pos = rc[1]; 
+		item[name] <- key;
+	}
+	return [item, pos];
+}
+
+function ParseGroup(pos, endpos, parent){
+	local rc, item
+	local group = [];
+	while (pos < endpos){
+		rc = ParseItem(pos, group);
+		item = rc[0]; pos = rc[1]; 
+		item.parent <- parent;
+		group.push(item);
+	}
+	return group;
+}
+
+function ParseAttributes(pos, endpos){
+	local rc, item, key;
+	local attr = {};
+	while (pos < endpos){
+		rc = GetItem(pos, "string");
+		key = rc[0]; pos = rc[1]; 
+		local type = Grammar.attr.get(key, false);
+		if (type){
+			rc = GetItem(pos, type);
+			item = rc[0]; pos = rc[1]; 
+			attr[key] <- item;
+		}
+		else attr[key] <- true;
+	}
+	return attr;
+}
+
+function OpenOutput(out){
+	if (type(configuration.indentation) == "integer"){
+		configuration.indentation = " ".rep(configuration.indentation);
+	}
+
+	local indstr = function(k){
+		return configuration.indentation.rep(k);
+	}
+	//local fended = true;
+	local fOutput = function(ind, ...){
+		//if (fended) 
+		out.push(indstr(ind));
+		local str = format.acall2(this, vargv);
+		//print(select(1, ...))
+		// Indent all code, except multi-line strings
+		if (! str.match("[^%-]%[=*%[.*\n.*%]=*%]") ){
+			str = str.gsub("([^\\\n]\n)(.)", "%1" + indstr(ind) + "%2");
+		}
+		out.push(str);
+		//fended = str.match("\n$");
+	}
+	return fOutput;
+}
+
+Write.Function <- function(t, ind){
+	Output(ind, "function %s\n", t.name);
+	t.varname <- "res";
+	Write.group(t.body, ind+1);
+	local names = [];
+	foreach(i in t.body) names.push(i.varname);
+	if (names.len() > 0) Output(ind+1, "return %s;\n", names.concat(", "));
+	Output(ind, "}\n\n");
+}
+
+Write.Atributes <- function(t, ind, name){
+	local lname;
+	local klass = t.attr.get("class", false) || t.key;
+	if (klass.match("^Fl_")) lname = name;
+	else lname = name ;
+
+	//if (klass.match("Fl_Button") t.attr.when = 12;
+	
+	foreach( k,v in t.attr) {
+		if (Grammar.methods.get(k, false) && v){
+			Output(ind, "%s.%s(", lname, k);
+			if (type(v) == "integer") Output(0, "%d", v);
+			else if (Grammar.konst.get(v, false)) Output(0, "%d", Grammar.konst[v]);
+			else if (v.match("^[A-Z_]+$") ) Output(0, "FL_%s", v);
+			else Output(0, "_tr %q", v);
+			Output(0, ");\n");
+		}			
+	}
+}
+
+Write.widget <- function(t, ind){
+	local fgroup = Grammar.groups.get(t.key, false);
+	if (Grammar.composed.get(t.key, false) && t.attr.get("type", false)){
+		t.key = t.key.slice(0,3) + t.attr.type + t.key.slice(2);
+		t.attr.type = null;
+	}
+	local klass = t.attr.get("class", false) || t.key;
+	local constClearLabel = "_ClearLabel";
+	local isClearLabel = false;
+	if (klass.match(constClearLabel)){ 
+		klass = klass.gsub(constClearLabel, ""); 
+		isClearLabel = true;
+	}
+	//if (klass.match("^Fl_")) klass = klass;
+	local ar = t.attr.xywh;
+	local x = ar[0], y = ar[1], w = ar[2], h = ar[3];
+	local name = configuration.currentvar;
+	t.xoffset <- t.parent.get("xoffset", "");
+	t.yoffset <- t.parent.get("yoffset", "");
+	local newMethodCallStr, firstParamStr;
+	if (klass.match("^fltk%.")) {
+		newMethodCallStr = "";
+		firstParamStr = "";
+	}
+	else
+	{
+		newMethodCallStr = "";
+		firstParamStr = "";
+	}
+	//print(t.key, name, klass)
+	Output(ind, "{\n"); 
+	++ind;
+	Output(ind, "local %s = %s%s(%s%s%d, %s%d, %d, %d", name, 
+		klass, newMethodCallStr, firstParamStr, t.xoffset, x, t.yoffset, y, w, h);
+	if (! isClearLabel && t.attr.get("label", false)) Output(0, ", %s(%q)", configuration.textfilter, t.attr.label);
+	Output(0, ");\n");
+
+	t.varname <- name;
+	if (t.name.len() > 0){ 
+		local obj_name;
+		if (t.name.find(" ") >= 0){
+			local tbl_name = [];
+			t.name.gmatch("%S+", function(word){
+				tbl_name.push(word);
+				return true;
+			});
+			obj_name = tbl_name[1];
+			local obj_fld_name ;
+			local sep_pos = obj_name.find(":");
+			if (sep_pos >= 0){
+				obj_fld_name = obj_name.slice(0, sep_pos-1);
+				obj_name = obj_name.slice(sep_pos+1);
+			}
+			else obj_fld_name = obj_name;
+
+			Output(ind, "db_%s_map(\"%s\", %s, \"%s\", %s);\n", tbl_name[0], obj_fld_name, name, 
+				tbl_name.get(2, "rw"), tbl_name.get(3, "0"));
+		}
+		else obj_name = t.name;
+
+		Output(ind, "%s = %s;\n", obj_name, name);
+		t.varname = t.name;
+	}
+	
+	Write.Atributes(t, ind, name);
+
+	local img = t.attr.get("image", false);
+	if (img){
+		local ext = img.match("%.(%a+)$").toupper();
+		Output(ind, "%s.image(Fl_%s_Image(%q));\n", name, Grammar.images[ext], img);
+	}
+	if (t.attr.get("modal", false)) Output(ind, "%s.set_modal();\n", name);
+	if (t.attr.get("non_modal", false)) Output(ind, "%s.set_non_modal();\n", name);
+	for(local i=0; i <= 3; ++i){
+		local l = t.attr.get("code" + i, false);
+		if (l) Output(ind, "%s\n", l);
+	}
+	if (t.attr.get("noborder", false)) Output(ind, "%s.clear_border();\n", name);
+	if (t.attr.get("size_range", false)) Output(ind, "%s.size_range(%s);\n", name, table.concat(t.attr.size_range, ", "));
+	local cb = t.attr.get("callback", false);
+	if (cb){
+		if (cb.match("^[%w_]+$")) Output(ind, "%s.callback(%s);\n", name, cb);
+		else
+		{
+			Output(ind, "%s.callback(function(sender, udata){\n", name);
+			Output(ind+1, "%s\n", cb);
+			Output(ind, "});\n");
+		}
+	}
+	if (t.get("body", false) && t.body.len() > 0) {
+		Output(ind, "{\n");
+		Write.group(t.body, ind+1);
+		Output(ind, "}\n");
+	}
+	
+	if (fgroup){ 
+		if (klass.match("^fltk%.")) Output(ind, "%s.end();\n", name);
+		else Output(ind, "%s.end();\n", name);
+	}
+	if (t.attr.get("resizable", false)) { 
+		if (t.parent.key != "Function"){
+			Output(ind, "Fl_Group.current().resizable(%s);\n", name);
+			t.parent.resized <- true;
+		}
+		else if (! t.get("resized", false) ) Output(ind, "%s.resizable(%s);\n", name, name);
+	}
+	Output(ind-1, "}\n"); 
+}
+
+Write.Submenu <- function(t, ind){
+	if (t.parent.path) t.path = t.parent.path + "/" + t.attr.label;
+	else t.path = t.attr.label;
+
+	Output(ind, "//%s %s\n", t.name, t.path);
+	if (t.body.len() > 0) Write.group(t.body, ind);
+	else Write.MenuItem(t, ind);
+}
+
+Write.MenuItem <- function(t, ind){
+	if (t.parent.path) t.path = t.parent.path + "/" +  (t.attr.label || "");
+	else t.path = t.attr.label;
+
+	local w = t;
+	while (!w.varname) w = w.parent;
+
+	local cb = t.attr.callback;
+	
+	if (!cb && t.name > ""){
+		cb = "dispatch_func(" + t.name + "_cb, self)";
+		//Output(ind, "%s = %s:add(%q", t.name, w.varname, t.path)
+		Output(ind, "%s = o.add(%q", t.name, t.path);
+	}
+	else
+	{
+		//Output(ind, "%s:add(%q", w.varname, t.path)
+		Output(ind, "o.add(%q", t.path);
+	}
+
+	Output(ind, ", %s", t.attr.shortcut || "null");
+	if (cb){
+		if (cb.match("^[%w_]+$")) Output(ind, ", %s", cb);
+		else
+		{
+			Output(ind, ", function(self){\n");
+			Output(ind+1, "%s\n", cb);
+			Output(ind, "}");
+		}
+
+		if (t.name > ""){
+			local ind2 = 0;
+			if (t.attr.deactivate) Output2(ind2, "// deactivated base_class.%s\n", t.name);
+			Output2(ind2, "function base_class.%s_cb(sender);\n", t.name);
+			Output2(ind2+2, "fl_alert(\"%s en construccion\");\n", t.name);
+			Output2(ind2, "}\n\n", t.name);
+		}
+	}
+	local type = Grammar.menu_const[t.attr.type];
+	if (t.attr.divider){ 
+		if (type) type = type + Grammar.menu_const.divider;
+		else type = Grammar.menu_const.divider;
+	}
+	if (t.attr.deactivate){ 
+		if (type) type = type + Grammar.menu_const.deactivate;
+		else type = Grammar.menu_const.deactivate ;
+	}
+	if (t.attr.hide) { 
+		if (type) type = type + Grammar.menu_const.hide;
+		else type = Grammar.menu_const.hide;
+	}
+	if (t.attr.value){
+		if (type) type = type + 4; // FL_MENU_VALUE = 4
+		else type = 4; // FL_MENU_VALUE = 4 
+	}
+	if (type) {
+		Output(ind, ", null".rep(cb && 1 || 3));
+		Output(ind, ", %s", type);
+	}
+	Output(0, ");\n");
+}
+
+Write.group <- function(t, ind){
+	foreach(i in t){
+		if (Write.get(i.key, false))	Write[i.key](i, ind);
+		else if (i.key.match("^Fl_")) Write.widget(i, ind);
+	}
+}
+
+Write.comment <- function(t, ind){
+	local text = "\n" + t.name;
+	text = text.gsub("(\n%s*)//", "%1//");
+	text = text.gsub("(\n%s*)([^-][^-])", "%1// %2");
+	Output(ind, "%s\n", text.slice(1,-1));
+}
+
+Write.codeblock <- function(t, ind){
+	Output(ind, "%s\n", t.name);
+	Write.group(t.body, ind+1);
+	Output(ind, "%s\n", t.attr.after or "}");
+}
+
+Write.code <- function(t, ind){
+	Output(ind, "%s\n", t.name);
+}
+
+Write.decl <- function(t, ind){}
+
+Write.declblock <- function(t, ind){
+	Output(ind, "%s\n", t.name);
+	Write.group(t.body, ind+1);
+	Output(ind, "%s\n", t.attr.after || "}");
+}
+
+Write["class"] <- function(t, ind){
+	Output(ind, "class %s extends %s {\n", t.name, t.get("class", "?"));
+	local vars = [];
+	FindMembers.group(t.body, vars);
+	WriteVariables(ind+1, vars, "class members");
+	Output(ind+1, "// Create member functions\n"	);
+	Write.group(t.body, ind+1);
+	if (t.constructor) Output(ind+1, "foreach(i in {%s}) i.show();\n", t.constructor);
+	Output(ind+1, "return %s;\n", t.name);
+	Output(ind, "}\n\n");
+}
+
+Write.widget_class <- function(t, ind){
+	local vars = [];
+	local wObj = "";
+	local typeName;
+	//if (t.attr.get("class", false) && t.attr["class"].match("^Fl_")) typeName = "fltk." + t.attr["class"];
+	//else  
+	typeName = t.attr["class"];
+
+	Output(ind, "class %s extends %s {\n", t.name, typeName);
+	local widgetType = typeName || "Fl_Group";
+	Output(ind+1, "\n")	;
+
+	FindMembers.group(t.body, vars);
+	WriteVariables(ind+1, vars, "class members");
+	
+	if (!t.attr.get("class", false) || (! t.attr["class"].match("^Fl_"))){
+		local strCreateWidget = format("constructor(){\n");
+		Output(ind+1, strCreateWidget);
+		local ar = t.attr.xywh;
+		local x = ar[0], y = ar[1], w = ar[2], h = ar[3];
+		Output(ind+2, "base.constructor(%d, %d, %d, %d);\n", x, y, w, h);
+		if (! (t.attr.get("class", "")).match("_Window$") ) {
+			t.xoffset <- "_x + ";
+			t.yoffset <- "_y + ";
+			Output(ind+2, "local _x = %d, _y = %d;\n", x, y);
+		}
+	}
+	else
+	{
+		local strCreateWidget = format("kTopW = %s.new_local(...);\n", widgetType);
+	
+		Output(ind+1, "// using top_level_window.new_local() to allow garbage collection\n");
+		Output(ind+1, "// but .new() on any other widget owned by top_level_window\n");
+		
+		if (t.attr.get("class", "").match("_Window$")){
+			Output(ind+1, "local _arg1_ = vargv;\n");
+			Output(ind+1, "if (!_arg1_){\n");
+			local ar = t.attr.xywh;
+			local x = ar[0], y = ar[1], w = ar[2], h = ar[3];
+			Output(ind+2, "kTopW = %s.new_local(%d, %d, %s %q);\n", widgetType, w, h, 
+				configuration.textfilter, t.attr.label);
+			local tmpType = t.attr.type;
+			t.attr.type = null;
+			Write.Atributes(t, ind+2, "");
+			t.attr.type = tmpType;
+			Output(ind+1, "} else {\n");
+			Output(ind+2, strCreateWidget);
+			Output(ind+1, "}\n");
+		}
+		else Output(ind+1, strCreateWidget);
+	}
+
+	FindMembers.group(t.body, vars);
+	//WriteVariables(ind+1, vars, "class members")	
+	Output(ind+2, "// Create member functions and widgets\n");
+	Write.group(t.body, ind+2);
+	
+	Output(ind+1, "}\n");
+	Output(ind, "}\n\n");
+}
+
+FindMembers.group <- function(t, list){
+	foreach(i in t){
+		if (FindMembers.get(i.key, false)) FindMembers[i.key](i, list);
+		else if (i.key.match("^Fl_")) FindMembers.widget(i, list);
+	}
+}
+
+function GetAccessMode(t, mode){
+	foreach(i in ["private", "protected", "public"]) if (t.attr.get(i, false)) mode = i;
+	return mode;
+}
+
+FindMembers.Function <- function(t, list){
+	if (t.name == "") t.name = "make_window()";
+	local name = t.name.match("[%w_]+");
+	if (t.parent.name == name) { // constructor
+		t.name = "__constructor()";
+		t.parent.constructor = t.name;
+	}
+	else 	list.push([ name, GetAccessMode(t, "public") ]);
+	FindMembers.group(t.body, list);
+}
+
+FindMembers["class"] <- function(t, list){
+	list.push([ t.name, "public" ]);
+}
+
+FindMembers.widget_class <- FindMembers["class"];
+
+FindMembers.widget <- function(t, list){
+	if (t.name.match("^[%w_]+[%.%[]")){
+		list.push([ t.name.match("^[%w_]+"), GetAccessMode(t, "public"), "{}" ]);
+	}
+	else if (t.name.match("^[%w_]+$")){
+		list.push([ t.name, GetAccessMode(t, "public") ]);
+	}
+	if (t.get("body", false)) FindMembers.group(t.body, list);
+}
+
+FindMembers.decl <- function(t, list){
+	list.push([ t.name, GetAccessMode(t, "private") ]);
+}
+
+function WriteVariables(ind, vars, type){
+	if (vars.len() == 0) return;
+	local defined = {};
+	Output(ind, "// Declaration of %s\n", type);
+	foreach(i in vars) {
+		if (defined.get(i[0], false)) {}
+		else if (i[1] == "public") Output(ind, "%s = null;\n", i[0]);
+		else Output(ind, "local %s = %s\n", i[0], i.get(2, "null"));
+		defined[i[0]] <- true;
+	}
+	Output(ind, "\n");
+}
+
+function WriteScript(tree){
+	local vars = [];
+	local ind = 0;
+	local fct = configuration.textfilter;
+	foreach(k in tree) if (k.key == "i18n_function") fct = fct || k.name;
+
+	configuration.textfilter = fct && fct + " " || "";
+	if (configuration.shebang){
+		if (configuration.shebang.match("\\") || configuration.shebang.match("%.[eE][xX][eE]")){
+			Output(ind, "rem=[[ Start Lua script\n");
+			Output(ind, "@echo off\n");
+			Output(ind, "%s %%0 %%*\n", configuration.shebang);
+			Output(ind, "exit /B\n]]\n\n");
+		}
+		else 	Output(ind, "#! %s\n", configuration.shebang);
+	}
+	FindMembers.group(tree, vars);
+	//WriteVariables(ind, vars, "global variables");
+	Write.group(tree, ind);
+	foreach(i in vars) {
+		if (i[0] == "main") Output(ind, "main(...){\n");
+		else if (i[0] == "make_window") Output(ind, "foreach(i in {make_window()}) i.show();\nFl.run();\n");
+	}
+}
+
+function DecodeOption(arg){
+	local config = {};
+	for(local i=0, len=arg.len(); i < len; i +=2){
+		if (arg[i].slice(0,1) != "-") {
+			local ar = [config];
+			for(local iv = i, ivlen = arg.len(); iv < ivlen; ++iv) ar.push(arg[iv]);
+			return ar;
+		}
+		local val = arg[i+1];
+		if (val.tointeger()) val = val.tointeger();
+		config[arg[i].slice(1)] <- val;
+	}
+}
+
+// Main global function
+function Fluid2SquiLu(infile, outfile, config){
+	configuration = {};
+	foreach( k,v in default_configuration) configuration[k] <- v;
+	foreach( k,v in config || {}) configuration[k] <- v;
+	Grammar = BuildGrammar();
+	source_file = ReadFile(infile);
+	local tree = ParseGroup(source_file.find("\n")+1, source_file.len(), {});
+	local outdata = [];
+	local outdata2 = [];
+	Output = OpenOutput(outdata);
+	Output2 = OpenOutput(outdata2);
+	WriteScript(tree);
+	outdata = outdata.concat();
+	outdata2 = outdata2.concat();
+	if (outfile == "-") print(outdata);
+	else if (outfile){
+		local fd = file(outfile, "wt");
+		fd.write(outdata);
+		fd.close();
+	}
+	if (outdata2.len() > 0){
+		local fd = file("extra-generated-code.lua", "wt");
+		fd.write(outdata2);
+		fd.close();
+	}
+	if (configuration.check == "syntax") assert(loadstring(outdata, "@" + (outfile || infile)));
+	else if (configuration.check == "run") assert(loadstring(outdata, "@" + (outfile || infile)))();
+	return outdata;
+}
+
+if (vargv.len() > 0){ 
+	local rc = DecodeOption(arg);
+	local config = rc[0], infile = rc[1], outfile = rc[2]; 
+	Fluid2SquiLu(infile, outfile, config);
+}
+Fluid2SquiLu("dadbiz-gui.fl", "-", {});

+ 661 - 0
ourbiz/index.tpl

@@ -0,0 +1,661 @@
+<!doctype html>
+<!--
+Design by Free Responsive Templates
+http://www.free-responsive-templates.com
+Released for free under a Creative Commons Attribution 3.0 Unported License (CC BY 3.0) 
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Companies Info UK</title>
+<link href="css/styles.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+article table td:nth-child(2), td:nth-child(3) {
+	text-align: right;
+}
+article table.nj td:nth-child(2), td:nth-child(3) {
+	text-align: left;
+}
+article table.dist td:nth-child(3), td:nth-child(4), td:nth-child(5)  {
+	text-align: right;
+}
+table {
+	margin-left:auto; 
+    margin-right:auto;
+}
+table, th, td
+{
+	border: 1px solid #ccc;
+}
+table td {
+	vertical-align:top;
+    padding-left: 0.5em;
+    padding-right: 0.5em;
+}
+  table.bold2 td:nth-child(2) {font-weight:bold;}
+.post header {
+      text-align:center;
+	float:none;
+	width:100%;
+	padding:0;
+}
+</style>
+  
+<?
+  local account_categories = [
+["TOTAL EXEMPTION SMALL","1,417,506","46.38%"],
+["NO ACCOUNTS FILED","837,086","27.39%"],
+["DORMANT","406,070","13.29%"],
+["TOTAL EXEMPTION FULL","164,883","5.40%"],
+["FULL","137,209","4.49%"],
+["SMALL","61,113","2.00%"],
+["GROUP","21,292","0.70%"],
+["MEDUM","5,523","0.18%"],
+["ACCOUNTS TYPE NOT AVAILABLE","5,099","0.17%"],
+["PARTIAL EXEMPTION","230","0.01%"],
+["INITIAL","7","0%"],  
+  ]
+
+  local company_categories = [
+["Private Limited Company","2,816,656","92.17%"],
+["PRI/LTD BY GUAR/NSC (Private, limited by guarantee, no share capital)","77,564","2.54%"],
+["Limited Liability Partnership","54,887","1.80%"],
+["PRI/LBG/NSC (Private, Limited by guarantee, no share capital, use of 'Limited' exemption)","39,623","1.30%"],
+["Limited Partnership","22,542","0.74%"],
+["Other company type","11,580","0.38%"],
+["Industrial and Provident Society","9,961","0.33%"],
+["Public Limited Company","8,473","0.28%"],
+["Community Interest Company","7,101","0.23%"],
+["Private Unlimited Company","6,011","0.20%"],
+["Royal Charter Company","832","0.03%"],
+["Investment Company with Variable Capital","500","0.02%"],
+["Private Unlimited","140","0.00%"],
+["Investment Company with Variable Capital(Umbrella)","99","0.00%"],
+["Old Public Company","22","0.00%"],
+["PRIV LTD SECT. 30 (Private limited company, section 30 of the Companies Act)","15","0.00%"],
+["Investment Company with Variable Capital (Securities)","12","0.00%"],
+  ]
+
+  local company_status = [
+["Active","2,824,726","92.43%"],
+["Active - Proposal to Strike off","139,788","4.57%"],
+["Liquidation","79,770","2.61%"],
+["In Administration","4,740","0.16%"],
+["Live but Receiver Manager on at least one charge","2,516","0.08%"],
+["Voluntary Arrangement","1,864","0.06%"],
+["ADMINISTRATIVE RECEIVER","1,492","0.05%"],
+["In Administration/Administrative Receiver","425","0.01%"],
+["RECEIVERSHIP","322","0.01%"],
+["ADMINISTRATION ORDER","189","0.01%"],
+["In Administration/Receiver Manager","102","0.00%"],
+["RECEIVER MANAGER / ADMINISTRATIVE RECEIVER","74","0.00%"],
+["VOLUNTARY ARRANGEMENT / RECEIVER MANAGER","8","0.00%"],
+["VOLUNTARY ARRANGEMENT / ADMINISTRATIVE RECEIVER","1","0.00%"],
+["VOLUNTARY ARRANGEMENT / RECEIVERSHIP","1","0.00%"],
+  ]
+
+local company_ages = [
+["475","1","0.00%"],
+["+150","75","0.00%"],
+["100-149","5,758","0.19%"],
+["50-99","53,788","1.76%"],
+["30-49","120,862","3.95%"],
+["20-29","175,876","5.76%"],
+["10-19","565,363","18.50%"],
+["5-9","719,719","23.55%"],
+["4","179,057","5.86%"],
+["3","233,894","7.65%"],
+["2","316,072","10.34%"],
+["1","451,577","14.78%"],
+["-1","233,976","7.66%"],    
+]
+
+function emptyOnNull(key){
+	local str = this.get(key, null);
+	return str ? str : "";
+}
+
+function getPageLink(page){
+	local fmt = "/?search_str=%s&search_post_code=%s&search_sic_code=%s&search_origin_post_code=%s&search_around_post_code=%s&page=%d";
+	return format(fmt, 
+		url_encode(emptyOnNull("search_str")),  
+		url_encode(emptyOnNull("search_post_code")),  
+		url_encode(emptyOnNull("search_sic_code")),
+		url_encode(emptyOnNull("search_origin_post_code")), 
+		url_encode(emptyOnNull("search_around_post_code")), 
+		page);
+}
+
+?>
+<? if (this.get("use_vjs", false) && this.get("page_name", null) == "search_results"){ ?>
+    <!--Load the AJAX API-->
+    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+    <script type="text/javascript">
+
+      // Load the Visualization API and the piechart package.
+      google.load('visualization', '1.0', {'packages':['corechart']});
+
+      // Set a callback to run when the Google Visualization API is loaded.
+      google.setOnLoadCallback(drawChart);
+
+      // Callback that creates and populates a data table,
+      // instantiates the pie chart, passes in the data and
+      // draws it.
+      function drawChart() {
+
+        // Create the data table.
+        var data = new google.visualization.DataTable();
+        data.addColumn('string', 'Topping');
+        data.addColumn('number', 'Slices');
+        data.addRows([
+          <? foreach(k,v in account_categories) { ?>
+          ["<?=v[0]?>", <?=v[1].gsub(",","")?>],
+          <? } ?>
+          ['', 0]
+        ]);
+
+        // Set chart options
+        var options = {'title':'Distribution of companies by Account Category',
+                       'width2':400,
+                       'height':300};
+
+        // Instantiate and draw our chart, passing in some options.
+        var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
+        chart.draw(data, options);
+        
+        // Create the data table.
+        var data2 = new google.visualization.DataTable();
+        data2.addColumn('string', 'Topping');
+        data2.addColumn('number', 'Slices');
+        data2.addRows([
+          <? foreach(k,v in company_categories){ ?>
+          ["<?=v[0]?>", <?=v[1].gsub(",","")?>],
+          <? } ?>
+          ['', 0]
+        ]);
+
+        // Set chart options
+        var options2 = {'title':'Distribution of companies by Company Category',
+                       'width2':400,
+                       'height':300};
+
+        // Instantiate and draw our chart, passing in some options.
+        var chart2 = new google.visualization.PieChart(document.getElementById('chart2_div'));
+        chart2.draw(data2, options2);
+        
+        // Create the data table.
+        var data3 = new google.visualization.DataTable();
+        data3.addColumn('string', 'Topping');
+        data3.addColumn('number', 'Slices');
+        data3.addRows([
+          <? foreach(k,v in company_status) { ?>
+          ["<?=v[0]?>", <?=v[1].gsub(",","")?>],
+          <? } ?>
+          ['', 0]
+        ]);
+
+        // Set chart options
+        var options3 = {'title':'Distribution of companies by Company Status',
+                       'width2':400,
+                       'height':300};
+
+        // Instantiate and draw our chart, passing in some options.
+        var chart3 = new google.visualization.PieChart(document.getElementById('chart3_div'));
+        chart3.draw(data3, options3);
+        
+        // Create the data table.
+        var data4 = new google.visualization.DataTable();
+        data4.addColumn('string', 'Topping');
+        data4.addColumn('number', 'Slices');
+        data4.addRows([
+          <? foreach(k,v in company_ages){ ?>
+          ["<?=v[0]?> years", <?=v[1].gsub(",","")?>],
+          <? } ?>
+          ['', 0]
+        ]);
+
+        // Set chart options
+        var options4 = {'title':'Distribution of companies by Age',
+                       'width2':400,
+                       'height':300};
+
+        // Instantiate and draw our chart, passing in some options.
+        var chart4 = new google.visualization.PieChart(document.getElementById('chart4_div'));
+        chart4.draw(data4, options4);
+	
+        var data5 = google.visualization.arrayToDataTable([
+          ['Year', 'Survive', 'Registered'],
+["2000",50134,210350],
+["2001",58321,231281],
+["2002",60334,211903],
+["2003",95499,280408],
+["2004",126032,378591],
+["2005",102056,317459],
+["2006",114497,341322],
+["2007",135753,374450],
+["2008",167628,423018],
+["2009",157289,320284],
+["2010",191538,333040],
+["2011",253577,365982],
+["2012",377167,413809],
+        ]);
+
+        var options5 = {
+          title: 'Historical Company Registered and Survival',
+          hAxis: {title: 'Year',  titleTextStyle: {color: 'red'}}
+        };
+
+        var chart5 = new google.visualization.ColumnChart(document.getElementById('chart5_div'));
+        chart5.draw(data5, options5);	
+      }
+    </script>
+<? } ?>
+<script type="text/javascript">
+function getCookie(c_name)
+{
+var i,x,y,ARRcookies=document.cookie.split(";");
+for (i=0;i<ARRcookies.length;i++)
+  {
+  x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
+  y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
+  x=x.replace(/^\s+|\s+$/g,"");
+  if (x==c_name)
+    {
+    return unescape(y);
+    }
+  }
+}
+
+function setCookie(c_name,value,exdays)
+{
+var exdate=new Date();
+exdate.setDate(exdate.getDate() + exdays);
+var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
+document.cookie=c_name + "=" + c_value;
+}
+
+var saveLoadFormFields = ['search_str', 'search_post_code', 'search_sic_code', 'search_origin_post_code', 'search_around_post_code'];
+function saveFormFields(frm){
+	for(var i=0; i< saveLoadFormFields.length; ++i){
+		setCookie(saveLoadFormFields[i], frm[saveLoadFormFields[i]].value, 180);
+	}
+	return true;
+}
+
+function loadFormFields(){
+	var frm = document.getElementById("search_form");
+	if(frm){
+		for(var i=0; i< saveLoadFormFields.length; ++i){
+			 frm[saveLoadFormFields[i]].value = getCookie(saveLoadFormFields[i]) || '';
+		}
+	}	
+}
+
+function show_location(position) {
+	var request;
+	if (window.XMLHttpRequest)  request = new XMLHttpRequest();     // Firefox, Safari, ...
+	else if (window.ActiveXObject)   request = new ActiveXObject("Microsoft.XMLHTTP"); // Internet Explorer
+	request.onreadystatechange = function(event, cached){
+		if (request.readyState != 4) return;
+		var cpc = document.getElementById("cpc");
+		cpc.value = request.responseText;
+	}
+	request.open("GET", "/getpc?lat=" +  position.coords.latitude + "&lon=" +position.coords.longitude, true);
+	request.send(null);
+}
+
+function get_post_code(){
+	navigator.geolocation.getCurrentPosition(show_location);
+}
+
+function setSicCode(code){
+	document.getElementById("search_form").search_sic_code.value=code
+}
+
+var isSortedByDistance = true;
+
+function sortTable(id, col, numeric){
+    var tbl = document.getElementById(id).tBodies[0];
+    var store = [];
+    for(var i=1, len=tbl.rows.length; i<len; i++){
+        store.push( tbl.rows[i]);
+    }
+    if(numeric){
+	store.sort(function(x,y){
+		var num1 = parseFloat(x.cells[col].textContent || row.cells[col].innerText);
+		var num2 = parseFloat(y.cells[col].textContent || row.cells[col].innerText);
+		return num1-num2;
+	});
+    } else {
+	store.sort(function(x,y){
+		var str1 = x.cells[col].textContent || row.cells[col].innerText;
+		var str2 = y.cells[col].textContent || row.cells[col].innerText;
+		return (str1 < str2 ? -1 : (str1 > str2 ? 1 : 0));
+	});
+    }
+    
+    for(var i=0, len=store.length; i<len; i++){
+        tbl.appendChild(store[i]);
+    }
+    store = null;
+    return false;
+}
+</script>
+</head>
+<body onload="loadFormFields()">
+<div class="wrapper">
+	<header>
+      <div class="logo"><h1><a href="/">CIUK</a></h1></div>
+        <nav>
+            <ul id="navlist">
+              <li id="active"><a href="/">Home</a></li>
+                <li><a href="#">About</a></li>
+                <li><a href="#">Shop</a></li>
+                <li><a href="#">Customers</a></li>
+                <li><a href="#">Contact</a></li>
+            </ul>
+        </nav>
+        <div class="clearfloat"></div>
+    </header>
+    <section>
+    	<div class="horSeparator"></div>
+    	<h1>Welcome to Companies Info UK</h1>
+        <p>
+        	Here you'll find interesting statistics and info about companies in UK.
+        </p>
+<form action="/#results" method="post" onsubmit="saveFormFields(this)" id="search_form">
+<table>
+<tr><td>Company Name</td><td><input type="text" name="search_str" value="<?=search_str?>" title="enter a company name to search"></td></tr>
+<tr><td>Post Code</td><td><input type="text" name="search_post_code" value="<?=search_post_code?>" title="enter a complete or parcial post code"></td></tr>
+<tr><td><select name="sic_street"><option value="sic">SIC Code</option><option value="street">Street</option></select></td>
+<td><input type="text" name="search_sic_code" value="<?=search_sic_code?>" title="enter a complete or parcial sic code"></td></tr>
+<tr><td>Your Post Code</td><td><input type="text" id="cpc" name="search_origin_post_code" value="<?=search_origin_post_code?>" title="enter your postcode if you want see distances" size="7">
+	<input type="text" name="search_around_post_code" value="<?=search_around_post_code?>" title="enter the distance in meters to search around your postcode" size="7">
+</td></tr>
+<tr><td><button type=submit>Search</button></td><td id="cloc"><button type=button onclick="get_post_code()">Get Postcode</button>
+	<button type=reset>Reset</button></td></tr>
+</table>
+</form>
+<? if (this.get("isAndroid", false)){ ?>
+<a href="/mk-gpx?sic_term=<?=search_sic_code?>">Generate GPX</a>
+<? } ?>
+        <div class="horSeparator"></div>
+    </section>
+    <article class="post">
+<? if (page_name == "search_results"){ ?>
+
+<? if (this.get("sic_street", null)  == "street"){ ?>
+
+<header><h1 id="results">Street Search Results</h1></header> 
+<? if (this.get("queryWasInterrupted", false)){ ?>
+<p>Please try again with more specific search terms, it took too long !</p>
+<? } ?>
+<? if (this.get("rows", false) && rows.len() > 0){ ?>
+<table class="nj">
+<tr><th>Company</th><th>Street</th><th>Postcode</th></tr>
+<? foreach( k, rec in rows){ ?>
+<tr><td><a href="view?id=<?=rec[0]?>#results"><?=rec[0]?></a></td><td><?=rec[1]?></td><td><?=rec[2]?></td></tr>
+<? }
+	page = page.tointeger();
+	local hasPrevious = page;
+	local hasNext = rows.len() == limit;
+	if (hasPrevious || hasNext){
+?>
+<tr><td>
+&nbsp;
+<? if (hasPrevious){ ?>
+<a href="/?search_sic_code=<?=url_encode(this.get("search_sic_code", ""))?>&page=<?=page-1?>">Prev</a>
+<? } ?>
+</td><td>&nbsp;</td><td>
+&nbsp;
+<? if (hasNext){ ?>
+<a href="/?search_sic_code=<?=url_encode(this.get("search_sic_code", ""))?>&page=<?=page+1?>">Next</a>
+<? } ?>
+</td></tr>
+<? } ?>
+</table>
+<? 
+	} 
+} else if (this.get("sicSearchResults", false)) { ?>
+
+<header><h1 id="results">SIC Code Search Results</h1></header> 
+<? if (this.get("queryWasInterrupted", false)){ ?>
+<p>Please try again with more specific search terms, it took too long !</p>
+<? } ?>
+<? if (this.get("rows", false) && rows.len() > 0){ ?>
+<table class="nj">
+<tr><th>Code</th><th>Description</th><th>#Companies</th></tr>
+<? foreach( k, rec in rows){ ?>
+<tr><td><a href="#search_form" onclick="setSicCode(<?=rec[1]?>)"><?=rec[1]?></a></td><td><?=rec[2]?></td><td><?=rec[3]?></td></tr>
+<? }
+	page = page.tointeger();
+	local hasPrevious = page > 0;
+	local hasNext = rows.len() == limit;
+	if (hasPrevious || hasNext){
+?>
+<tr><td>
+&nbsp;
+<? if (hasPrevious){ ?>
+<a href="/?search_sic_code=<?=url_encode(this.get("search_sic_code", ""))?>&page=<?=page-1?>">Prev</a>
+<? } ?>
+</td><td>&nbsp;</td><td>
+&nbsp;
+<? if (hasNext){ ?>
+<a href="/?search_sic_code=<?=url_encode(this.get("search_sic_code", ""))?>&page=<?=page+1?>">Next</a>
+<? } ?>
+</td></tr>
+<? } ?>
+</table>
+<? 
+	} 
+} else { ?>
+
+<header><h1 id="results">Companies Search Results</h1></header> 
+<? if (this.get("queryWasInterrupted",false)) { ?>
+<p>Please try again with more specific search terms, it took too long !</p>
+<? } ?>
+<? if (this.get("rows", false) && rows.len() > 0){ ?>
+<table class="nj dist" id="tblcr">
+<tr><th><a href="" onclick="return sortTable('tblcr', 0)">Number</a></th>
+	<th><a href="" onclick="return sortTable('tblcr', 1)">Name</a></th>
+	<th><a href="" onclick="return sortTable('tblcr', 2, true)">Age (years)</a></th>
+<? 
+	local hasDistances = this.get("search_origin_post_code", false) && search_origin_post_code.len() > 0; 
+	if (hasDistances){ 
+?>
+<th><a href="" onclick="return sortTable('tblcr', 3, true)">Dist. Meters</a></th>
+<? } ?>
+<th>Google</th></tr>
+<? foreach( k, rec in rows){ ?>
+<tr><td><?=rec[1]?></td><td><a href="view?id=<?=rec[0]?>#results"><?=rec[2]?></a></td><td><?=rec[3]?></td>
+<?if (hasDistances){ ?>
+<td><?=rec[5]?> <img src="images/small-arrow.png"  style="transform:rotate(<?=rec[6]?>deg);-webkit-transform:rotate(<?=rec[6]?>deg)"></td>
+<? } ?>
+<td><a href="http://www.google.co.uk/search?q=<?=url_encode(format("%s %s", rec[2], rec[4]))?>" target="gsearch">Google</a></td></tr>
+<? }
+	page = page.tointeger();
+	local hasPrevious = page > 0;
+	local hasNext = rows.len() == limit;
+	if (hasPrevious || hasNext){
+?>
+<tr><td>
+&nbsp;
+<? if (hasPrevious){ ?>
+<a href="<?=getPageLink(page-1)?>#results">Prev</a>
+<? } ?>
+</td><td>&nbsp;</td><td>
+&nbsp;
+<? if (hasNext){ ?>
+<a href="<?=getPageLink(page+1)?>#results">Next</a>
+<? } ?>
+</td>
+<?if (hasDistances){ ?>
+<td>&nbsp;</td>
+<? } ?>
+<td>&nbsp;</td></tr>
+<? } ?>
+</table>
+<? 		
+		} 
+	} 
+ }
+   else if (page_name == "view_company") {
+       var pc1, pc2, google_map_url, geo_link;
+       if (company.get("post_code", false) && company.post_code.len() > 0){
+    	company.post_code.gmatch("([^%s]+)%s([^%s]+)", function(m1,m2) {pc1=m1;pc2=m2;});
+        if (pc1 && pc2){
+          google_map_url = format("https://maps.google.co.uk/maps?key=AIzaSyAF53Wut8B5cvaUDY-pfegBhbftJdRHovM&amp;channel=cs&amp;q=%s+%s&amp;ie=UTF8&amp;hq=&amp;hnear=%s+%s,+United+Kingdom&amp;gl=uk&amp;t=m&amp;z=14&amp;source=embed", pc1, pc2, pc1, pc2);
+        }
+	if (longitude) geo_link = format("geo:%f,%f&z=16", latitude,longitude);
+	else  geo_link = "#";
+?>
+    
+<header><h1 id="results"><?=company.number?> - <?=company.name?></h1></header>
+<table class="nj dist">
+<tr><td>Address</td><td>
+<?=company.address?><br>
+<?=company.address2?><br>
+<?=company.post_town?><br>
+<?=company.county?><br>
+</td></tr>
+<tr><td>Post code</td><td>
+<a href="<?=geo_link?>"><?=company.post_code?></a>
+<? if (google_map_url){ ?>
+  <small><a href="<?=google_map_url?>" style="color:#0000FF;text-align:right" target="ViewOnMap">View Map</a></small>
+<? } ?>
+</td></tr>
+<tr><td>Status</td><td><?=company.status?></td></tr>
+<tr><td>Date of Incorporation</td><td><?=company.incorporation_date?></td></tr>
+<tr><td>Country of Origin</td><td><?=company.country_of_origin?></td></tr>
+<tr><td>Accounting Reference Date</td><td><?=company.incorporation_date?></td></tr>
+<tr><td>Last Accounts Made Up To</td><td><?=company.account_last_made_up_date?></td></tr>
+<tr><td>Next Accounts Due</td><td><?=company.account_next_due_date?></td></tr>
+<tr><td>Last Return Made Up To</td><td><?=company.returns_last_made_up_date?></td></tr>
+<tr><td>Next Return Due</td><td><?=company.returns_next_due_date?></td></tr>
+<tr><td>Company Type</td><td><?=company.category?></td></tr>
+<tr><td>Nature of Business (SIC)</td><td>
+<? foreach(k,v in company_sic_codes){ ?>
+<?=v[0]?> - <?=v[1]?><br>
+<? } ?>
+</td></tr>
+<tr><td>Previous Names</td><td>
+<? if (this.get("company_old_names", false) && company_old_names.len() > 0){ ?>
+<table>
+<tr><th>Date of change</th><th>Previous Name</th></tr>
+<? foreach(k,v in company_old_names){ ?>
+<tr><td><?=v[0]?></td><td><?=v[1]?></td></tr>
+<? } ?>
+</table>
+<? } ?>
+</td></tr>
+</table>
+<? if (this.get("extra_data", false) && extra_data.len() > 0){ ?>
+        <table>
+          <tr><th>Doc. Type</th><th>Date</th><th>Description</th></tr>
+          <? foreach(k,v in extra_data.split("\n")){
+              local rec = v.split("|");
+          ?>
+          <tr><td><?=rec[0]?></td><td><?=rec[1]?></td><td><?=rec[2]?></td></tr>
+          <? } ?>
+        </table>
+<? } ?>
+      
+<?
+  if (this.get("show_map", false) && pc1 && pc2){
+?>
+<br />
+<div style="margin: 0 auto; width: 425px;">
+<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" 
+src="https://maps.google.co.uk/maps?key=AIzaSyAF53Wut8B5cvaUDY-pfegBhbftJdRHovM&amp;channel=cs&amp;q=<?=pc1?>+<?=pc2?>&amp;ie=UTF8&amp;hq=&amp;hnear=<?=pc1?>+<?=pc2?>,+United+Kingdom&amp;gl=uk&amp;t=m&amp;z=14&amp;output=embed"></iframe>
+  <br /><small><a href="<?=google_map_url?>" style="color:#0000FF;text-align:left">View Larger Map</a></small>
+</div>
+<?
+	}
+   }
+} ?>
+    </article>
+<? if (page_name == "search_results"){ ?>
+    <article class="post">
+    	<header><h1>Distribution of companies by Account Category</h1></header>
+        <table>
+          <tr><th>Account Category</th><th>Companies</th><th>%Total</th></tr>
+          <tr><td>All Companies</td><td>3,056,018</td><td>100%</td></tr>
+          <? foreach(k,v in account_categories){ ?>
+          <tr><td><?=v[0]?></td><td><?=v[1]?></td><td><?=v[2]?></td></tr>
+          <? } ?>
+        </table>
+    <!--Div that will hold the pie chart-->
+    <div id="chart_div"></div>
+      
+        <div class="clearfloat"></div>
+    </article>
+    <article class="post">
+    	<header><h1>Distribution of companies by Company Category</h1></header>
+        <table>
+          <tr><th>Company Category</th><th>Companies</th><th>%Total</th></tr>
+          <tr><td>All Companies</td><td>3,056,018</td><td>100%</td></tr>
+          <? foreach(k,v in company_categories){ ?>
+          <tr><td><?=v[0]?></td><td><?=v[1]?></td><td><?=v[2]?></td></tr>
+          <? } ?>
+        </table>
+    <!--Div that will hold the pie chart-->
+    <div id="chart2_div"></div>
+        <div class="clearfloat"></div>
+    </article>
+    <article class="post">
+    	<header><h1>Distribution of companies by Company Status</h1></header>
+        <table>
+          <tr><th>Company Status</th><th>Companies</th><th>%Total</th></tr>
+          <tr><td>All Companies</td><td>3,056,018</td><td>100%</td></tr>
+          <? foreach(k,v in company_status){ ?>
+          <tr><td><?=v[0]?></td><td><?=v[1]?></td><td><?=v[2]?></td></tr>
+          <? } ?>
+      </table>
+    <!--Div that will hold the pie chart-->
+    <div id="chart3_div"></div>
+        <div class="clearfloat"></div>
+    </article>
+    <article class="post">
+    	<header><h1>Distribution of companies by Age (years)</h1></header>
+        <table>
+          <tr><th>Age(years)</th><th>Companies</th><th>%Total</th></tr>
+          <tr><td>All Companies</td><td>3,056,018</td><td>100%</td></tr>
+          <? foreach(k,v in company_ages){ ?>
+          <tr><td><?=v[0]?></td><td><?=v[1]?></td><td><?=v[2]?></td></tr>
+          <? } ?>
+      </table>
+    <!--Div that will hold the pie chart-->
+    <div id="chart4_div"></div>
+        <div class="clearfloat"></div>
+
+    <!--Div that will hold the pie chart-->
+    <div id="chart5_div"></div>
+        <div class="clearfloat"></div>
+    </article>
+<? } ?>
+    <section class="sectionFooter">
+    	<div class="footerBox">
+        	<h2>Free data from <a href="http://www.companieshouse.gov.uk/index.shtml">Companies House</a></h2>
+            <p>
+            	The Free Public Data Product is a downloadable data snapshot containing basic company data of live companies on the register. This snapshot is provided as ZIP files containing data in CSV format and is split into multiple files for ease of downloading.
+            </p>
+        </div>
+        <div class="footerBox">
+        	<h2>Free data from <a href="https://www.ordnancesurvey.co.uk/">Ordnance Survey</a></h2>
+            <p>
+            	Code-Point Open provides a precise geographic location for each postcode unit in Great Britain. The product is a CSV file containing postcodes, grid references, NHS® health and regional health authority codes, administrative ward, district, county and country area codes.
+            </p>
+        </div>
+        <div class="clearfloat"></div>
+    </section>
+</div>
+<footer>
+	<p>
+        Copyright &copy; Domingo Alvarez Duarte. All rights reserved. Designed by <a href="http://www.free-responsive-templates.com" title="free responsive templates">Free Responsive Templates</a>, Validation 
+        <a class="footerLink" href="http://validator.w3.org/check/referer" title="This page validates as HTML5"><abbr title="HyperText Markup Language">HTML5</abbr></a> | 
+        <a class="footerLink" href="http://jigsaw.w3.org/css-validator/check/referer" title="This page validates as CSS"><abbr title="Cascading Style Sheets">CSS3</abbr></a>
+    </p>
+</footer>
+</body>
+</html>

+ 614 - 0
ourbiz/invoice-A4.nut

@@ -0,0 +1,614 @@
+class Fl_Box_ClearLabel extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+	
+//class InvoiceA4 extends Fl_Group {
+class InvoiceA4 extends Fl_Window {
+	page=null;
+	pageDesignGroup=null;
+	logoGroupH=null;
+	logoH=null;
+	companyBoxH=null;
+	logoGroupV=null;
+	logoV=null;
+	companyBoxHV=null;
+	companyBoxV=null;
+	logoGroupHV=null;
+	logoGroupHV=null;
+	logoHV1=null;
+	logoHV2=null;
+	OrderNumber=null;
+	box_header_number_date=null;
+	box_data_number_date=null;
+	header_date_box=null;
+	box_data_date_box=null;
+	box_to=null;
+	orderLines=null;
+	header_lines_code_box=null;
+	header_lines_description_box=null;
+	header_lines_quantity_box=null;
+	header_lines_price_box=null;
+	header_lines_discount_box=null;
+	header_lines_sales_tax1_box=null;
+	header_lines_sales_tax2_box=null;
+	header_lines_subtotal_box=null;
+	designLinesGroup=null;
+	data_lines_code_box=null;
+	data_lines_description_box=null;
+	data_lines_quantity_box=null;
+	data_tlines_price_box=null;
+	data_lines_discount_box=null;
+	data_lines_sales_tax1_box=null;
+	data_lines_sales_tax2_box=null;
+	data_lines_subtotal_box=null;
+	orderTotals=null;
+	header_PAGENO_box=null;
+	box_data_pageno_box=null;
+	header_totals_subtotal_box=null;
+	data_totals_subtotal_box=null;
+	header_totals_total_sales_tax1_box=null;
+	data_totals_total_sales_tax1_box=null;
+	header_totals_total_sales_tax2_box=null;
+	data_totals_total_sales_tax2_box=null;
+	header_totals_total_box=null;
+	data_totals_total_box=null;
+	notes_box=null;
+	printDataGroup=null;
+	orderTypeBox=null;
+	numberBox=null;
+	dateBox=null;
+	entityBox=null;
+	dataLinesGroup=null;
+	codeBox=null;
+	descriptionBox=null;
+	quantityBox=null;
+	priceBox=null;
+	discountBox=null;
+	sales_tax1Box=null;
+	sales_tax2Box=null;
+	lineTotalBox=null;
+	bottomTotals=null;
+	orderPageBox=null;
+	fisrtTotalBox=null;
+	sales_tax1AmountBox=null;
+	sales_tax2AmountBox=null;
+	totalBox=null;
+	
+constructor() {
+	base.constructor(10, 50, 634, 686, _tr("InvoiceA4"));
+begin();
+this->box(FL_FLAT_BOX);
+this->color(FL_BACKGROUND_COLOR);
+this->selection_color(FL_BACKGROUND_COLOR);
+this->labeltype(FL_NO_LABEL);
+this->labelfont(0);
+this->labelsize(14);
+this->labelcolor(FL_FOREGROUND_COLOR);
+this->align((FL_ALIGN_TOP));
+this->when(FL_WHEN_RELEASE);
+{ page = new Fl_Group(0, 0, 634, 686);
+  page->color(FL_BACKGROUND2_COLOR);
+  { pageDesignGroup = new Fl_Group(2, 0, 630, 686);
+    pageDesignGroup->labeltype(FL_NO_LABEL);
+    { logoGroupH = new Fl_Group(15, 10, 316, 130);
+      logoGroupH->hide();
+      { logoH = new Fl_Box(16, 10, 310, 50, _tr("FLTK"));
+        logoH->labeltype(FL_SHADOW_LABEL);
+        logoH->labelfont(3);
+        logoH->labelsize(40);
+        logoH->align((644|FL_ALIGN_INSIDE));
+      } // Fl_Box* logoH
+      { companyBoxH = new Fl_Box_ClearLabel(16, 65, 308, 75, _tr(@"FLTK (pronounced ""fulltick"") is a cross-platform C++ GUI toolkit for UNIX\
+\302\256/Linux\302\256 (X11), Microsoft\302\256 Windows\302\256, and MacOS\
+\302\256 X. FLTK provides modern GUI functionality without the bloat and suppo\
+rts 3D graphics via OpenGL\302\256 and its built-in GLUT emulation."));
+        companyBoxH->box(FL_NO_BOX);
+        companyBoxH->color(FL_BACKGROUND_COLOR);
+        companyBoxH->selection_color(FL_BACKGROUND_COLOR);
+        companyBoxH->labeltype(FL_NORMAL_LABEL);
+        companyBoxH->labelfont(2);
+        companyBoxH->labelsize(10);
+        companyBoxH->labelcolor(FL_FOREGROUND_COLOR);
+        companyBoxH->align((FL_ALIGN_WRAP|FL_ALIGN_INSIDE));
+        companyBoxH->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* companyBoxH
+      logoGroupH->end();
+    } // Fl_Group* logoGroupH
+    { logoGroupV = new Fl_Group(15, 10, 316, 130);
+      logoGroupV->hide();
+      { logoV = new Fl_Box(16, 10, 100, 130, _tr("FLTK"));
+        logoV->labeltype(FL_SHADOW_LABEL);
+        logoV->labelfont(3);
+        logoV->labelsize(40);
+        logoV->align((644|FL_ALIGN_INSIDE));
+      } // Fl_Box* logoV
+      { companyBoxV = new Fl_Box_ClearLabel(120, 10, 210, 130, _tr(@"FLTK (pronounced ""fulltick"") is a cross-platform C++ GUI toolkit for UNIX\
+\302\256/Linux\302\256 (X11), Microsoft\302\256 Windows\302\256, and MacOS\
+\302\256 X. FLTK provides modern GUI functionality without the bloat and suppo\
+rts 3D graphics via OpenGL\302\256 and its built-in GLUT emulation."));
+        companyBoxV->box(FL_NO_BOX);
+        companyBoxV->color(FL_BACKGROUND_COLOR);
+        companyBoxV->selection_color(FL_BACKGROUND_COLOR);
+        companyBoxV->labeltype(FL_NORMAL_LABEL);
+        companyBoxV->labelfont(2);
+        companyBoxV->labelsize(10);
+        companyBoxV->labelcolor(FL_FOREGROUND_COLOR);
+        companyBoxV->align((FL_ALIGN_WRAP|FL_ALIGN_INSIDE));
+        companyBoxV->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* companyBoxV
+      logoGroupV->end();
+    } // Fl_Group* logoGroupV
+    { logoGroupHV = new Fl_Group(15, 10, 316, 130);
+      { logoHV1 = new Fl_Box(16, 10, 100, 130, _tr("FLTK"));
+        logoHV1->labeltype(FL_SHADOW_LABEL);
+        logoHV1->labelfont(3);
+        logoHV1->labelsize(40);
+        logoHV1->align((644|FL_ALIGN_INSIDE));
+      } // Fl_Box* logoHV1
+      { logoHV2 = new Fl_Box(120, 10, 210, 50, _tr("FLTK"));
+        logoHV2->labeltype(FL_SHADOW_LABEL);
+        logoHV2->labelfont(3);
+        logoHV2->labelsize(40);
+        logoHV2->align((644|FL_ALIGN_INSIDE));
+      } // Fl_Box* logoHV2
+      { companyBoxHV = new Fl_Box_ClearLabel(120, 50, 210, 90, _tr(@"FLTK (pronounced ""fulltick"") is a cross-platform C++ GUI toolkit for UNIX\
+\302\256/Linux\302\256 (X11), Microsoft\302\256 Windows\302\256, and MacOS\
+\302\256 X. FLTK provides modern GUI functionality without the bloat and suppo\
+rts 3D graphics via OpenGL\302\256 and its built-in GLUT emulation."));
+        companyBoxHV->box(FL_NO_BOX);
+        companyBoxHV->color(FL_BACKGROUND_COLOR);
+        companyBoxHV->selection_color(FL_BACKGROUND_COLOR);
+        companyBoxHV->labeltype(FL_NORMAL_LABEL);
+        companyBoxHV->labelfont(2);
+        companyBoxHV->labelsize(9);
+        companyBoxHV->labelcolor(FL_FOREGROUND_COLOR);
+        companyBoxHV->align((FL_ALIGN_WRAP|FL_ALIGN_INSIDE));
+        companyBoxHV->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* companyBoxHV
+      logoGroupHV->end();
+    } // Fl_Group* logoGroupHV
+    { OrderNumber = new Fl_Group(336, 10, 286, 40);
+      OrderNumber->box(FL_FLAT_BOX);
+      OrderNumber->color(FL_DARK3);
+      OrderNumber->labeltype(FL_NO_LABEL);
+      { box_header_number_date = new Fl_Box(337, 11, 142, 18);
+        box_header_number_date->box(FL_FLAT_BOX);
+        box_header_number_date->color(FL_DARK1);
+        box_header_number_date->labeltype(FL_NO_LABEL);
+        box_header_number_date->labelsize(12);
+      } // Fl_Box* box_header_number_date
+      { box_data_number_date = new Fl_Box(337, 30, 142, 19);
+        box_data_number_date->box(FL_FLAT_BOX);
+        box_data_number_date->color(FL_BACKGROUND2_COLOR);
+        box_data_number_date->labeltype(FL_NO_LABEL);
+        box_data_number_date->labelsize(12);
+      } // Fl_Box* box_data_number_date
+      { header_date_box = new Fl_Box(480, 11, 141, 18, _tr("DATE"));
+        header_date_box->box(FL_FLAT_BOX);
+        header_date_box->color(FL_DARK1);
+        header_date_box->labelfont(1);
+        header_date_box->labelsize(12);
+      } // Fl_Box* header_date_box
+      { box_data_date_box = new Fl_Box(480, 30, 141, 19);
+        box_data_date_box->box(FL_FLAT_BOX);
+        box_data_date_box->color(FL_BACKGROUND2_COLOR);
+        box_data_date_box->labeltype(FL_NO_LABEL);
+        box_data_date_box->labelfont(1);
+        box_data_date_box->labelsize(12);
+      } // Fl_Box* box_data_date_box
+      OrderNumber->end();
+    } // Fl_Group* OrderNumber
+    { box_to = new Fl_Box(336, 55, 286, 85);
+      box_to->box(FL_BORDER_FRAME);
+      box_to->color(FL_DARK3);
+      box_to->labelfont(1);
+      box_to->labelsize(16);
+      box_to->align((FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
+    } // Fl_Box* box_to
+    { orderLines = new Fl_Group(16, 148, 606, 433);
+      orderLines->box(FL_FLAT_BOX);
+      orderLines->color(FL_DARK3);
+      orderLines->labeltype(FL_NO_LABEL);
+      { header_lines_code_box = new Fl_Box(17, 149, 46, 20, _tr("CODE"));
+        header_lines_code_box->box(FL_FLAT_BOX);
+        header_lines_code_box->color(FL_DARK1);
+        header_lines_code_box->labelfont(1);
+        header_lines_code_box->labelsize(10);
+      } // Fl_Box* header_lines_code_box
+      { header_lines_description_box = new Fl_Box(64, 149, 300, 20, _tr("DESCRIPTION"));
+        header_lines_description_box->box(FL_FLAT_BOX);
+        header_lines_description_box->color(FL_DARK1);
+        header_lines_description_box->labelfont(1);
+        header_lines_description_box->labelsize(10);
+      } // Fl_Box* header_lines_description_box
+      { header_lines_quantity_box = new Fl_Box(365, 149, 40, 20, _tr("QTY."));
+        header_lines_quantity_box->box(FL_FLAT_BOX);
+        header_lines_quantity_box->color(FL_DARK1);
+        header_lines_quantity_box->labelfont(1);
+        header_lines_quantity_box->labelsize(10);
+      } // Fl_Box* header_lines_quantity_box
+      { header_lines_price_box = new Fl_Box(406, 149, 60, 20, _tr("PRICE"));
+        header_lines_price_box->box(FL_FLAT_BOX);
+        header_lines_price_box->color(FL_DARK1);
+        header_lines_price_box->labelfont(1);
+        header_lines_price_box->labelsize(10);
+      } // Fl_Box* header_lines_price_box
+      { header_lines_discount_box = new Fl_Box(467, 149, 30, 20, _tr("DISC. %"));
+        header_lines_discount_box->box(FL_FLAT_BOX);
+        header_lines_discount_box->color(FL_DARK1);
+        header_lines_discount_box->labelfont(1);
+        header_lines_discount_box->labelsize(8);
+        header_lines_discount_box->align((FL_ALIGN_WRAP));
+      } // Fl_Box* header_lines_discount_box
+      { header_lines_sales_tax1_box = new Fl_Box(498, 149, 30, 20, _tr("S.T. I %"));
+        header_lines_sales_tax1_box->box(FL_FLAT_BOX);
+        header_lines_sales_tax1_box->color(FL_DARK1);
+        header_lines_sales_tax1_box->labelfont(1);
+        header_lines_sales_tax1_box->labelsize(8);
+        header_lines_sales_tax1_box->align((FL_ALIGN_WRAP));
+      } // Fl_Box* header_lines_sales_tax1_box
+      { header_lines_sales_tax2_box = new Fl_Box(529, 149, 30, 20, _tr("S.T. II %"));
+        header_lines_sales_tax2_box->box(FL_FLAT_BOX);
+        header_lines_sales_tax2_box->color(FL_DARK1);
+        header_lines_sales_tax2_box->labelfont(1);
+        header_lines_sales_tax2_box->labelsize(8);
+        header_lines_sales_tax2_box->align((FL_ALIGN_WRAP));
+      } // Fl_Box* header_lines_sales_tax2_box
+      { header_lines_subtotal_box = new Fl_Box(560, 149, 61, 20, _tr("SUBTOTAL"));
+        header_lines_subtotal_box->box(FL_FLAT_BOX);
+        header_lines_subtotal_box->color(FL_DARK1);
+        header_lines_subtotal_box->labelfont(1);
+        header_lines_subtotal_box->labelsize(10);
+      } // Fl_Box* header_lines_subtotal_box
+      { designLinesGroup = new Fl_Group(17, 170, 604, 410);
+        designLinesGroup->labeltype(FL_NO_LABEL);
+        { data_lines_code_box = new Fl_Box(17, 170, 46, 410);
+          data_lines_code_box->box(FL_FLAT_BOX);
+          data_lines_code_box->color(FL_BACKGROUND2_COLOR);
+          data_lines_code_box->labeltype(FL_NO_LABEL);
+          data_lines_code_box->labelfont(1);
+          data_lines_code_box->labelsize(10);
+        } // Fl_Box* data_lines_code_box
+        { data_lines_description_box = new Fl_Box(64, 170, 300, 410);
+          data_lines_description_box->box(FL_FLAT_BOX);
+          data_lines_description_box->color(FL_BACKGROUND2_COLOR);
+          data_lines_description_box->labeltype(FL_NO_LABEL);
+          data_lines_description_box->labelfont(1);
+          data_lines_description_box->labelsize(10);
+        } // Fl_Box* data_lines_description_box
+        { data_lines_quantity_box = new Fl_Box(365, 170, 40, 410);
+          data_lines_quantity_box->box(FL_FLAT_BOX);
+          data_lines_quantity_box->color(FL_BACKGROUND2_COLOR);
+          data_lines_quantity_box->labeltype(FL_NO_LABEL);
+          data_lines_quantity_box->labelfont(1);
+          data_lines_quantity_box->labelsize(10);
+        } // Fl_Box* data_lines_quantity_box
+        { data_tlines_price_box = new Fl_Box(406, 170, 60, 410);
+          data_tlines_price_box->box(FL_FLAT_BOX);
+          data_tlines_price_box->color(FL_BACKGROUND2_COLOR);
+          data_tlines_price_box->labeltype(FL_NO_LABEL);
+          data_tlines_price_box->labelfont(1);
+          data_tlines_price_box->labelsize(10);
+        } // Fl_Box* data_tlines_price_box
+        { data_lines_discount_box = new Fl_Box(467, 170, 30, 410);
+          data_lines_discount_box->box(FL_FLAT_BOX);
+          data_lines_discount_box->color(FL_BACKGROUND2_COLOR);
+          data_lines_discount_box->labeltype(FL_NO_LABEL);
+          data_lines_discount_box->labelfont(1);
+          data_lines_discount_box->labelsize(10);
+        } // Fl_Box* data_lines_discount_box
+        { data_lines_sales_tax1_box = new Fl_Box(498, 170, 30, 410);
+          data_lines_sales_tax1_box->box(FL_FLAT_BOX);
+          data_lines_sales_tax1_box->color(FL_BACKGROUND2_COLOR);
+          data_lines_sales_tax1_box->labeltype(FL_NO_LABEL);
+          data_lines_sales_tax1_box->labelfont(1);
+          data_lines_sales_tax1_box->labelsize(10);
+        } // Fl_Box* data_lines_sales_tax1_box
+        { data_lines_sales_tax2_box = new Fl_Box(529, 170, 30, 410);
+          data_lines_sales_tax2_box->box(FL_FLAT_BOX);
+          data_lines_sales_tax2_box->color(FL_BACKGROUND2_COLOR);
+          data_lines_sales_tax2_box->labeltype(FL_NO_LABEL);
+          data_lines_sales_tax2_box->labelfont(1);
+          data_lines_sales_tax2_box->labelsize(10);
+        } // Fl_Box* data_lines_sales_tax2_box
+        { data_lines_subtotal_box = new Fl_Box(560, 170, 61, 410);
+          data_lines_subtotal_box->box(FL_FLAT_BOX);
+          data_lines_subtotal_box->color(FL_BACKGROUND2_COLOR);
+          data_lines_subtotal_box->labeltype(FL_NO_LABEL);
+          data_lines_subtotal_box->labelfont(1);
+          data_lines_subtotal_box->labelsize(10);
+        } // Fl_Box* data_lines_subtotal_box
+        designLinesGroup->end();
+        Fl_Group.current()->resizable(designLinesGroup);
+      } // Fl_Group* designLinesGroup
+      orderLines->end();
+      Fl_Group.current()->resizable(orderLines);
+    } // Fl_Group* orderLines
+    { orderTotals = new Fl_Group(16, 585, 606, 46);
+      orderTotals->box(FL_FLAT_BOX);
+      orderTotals->color(FL_DARK3);
+      orderTotals->labeltype(FL_NO_LABEL);
+      { header_PAGENO_box = new Fl_Box(17, 586, 65, 20, _tr("PAGE"));
+        header_PAGENO_box->box(FL_FLAT_BOX);
+        header_PAGENO_box->color(FL_DARK1);
+        header_PAGENO_box->labelfont(1);
+        header_PAGENO_box->labelsize(12);
+      } // Fl_Box* header_PAGENO_box
+      { box_data_pageno_box = new Fl_Box(17, 607, 65, 23);
+        box_data_pageno_box->box(FL_FLAT_BOX);
+        box_data_pageno_box->color(FL_BACKGROUND2_COLOR);
+        box_data_pageno_box->labeltype(FL_NO_LABEL);
+        box_data_pageno_box->labelfont(1);
+        box_data_pageno_box->labelsize(12);
+      } // Fl_Box* box_data_pageno_box
+      { header_totals_subtotal_box = new Fl_Box(83, 586, 150, 20, _tr("SUBTOTAL"));
+        header_totals_subtotal_box->box(FL_FLAT_BOX);
+        header_totals_subtotal_box->color(FL_DARK1);
+        header_totals_subtotal_box->labelfont(1);
+        header_totals_subtotal_box->labelsize(12);
+      } // Fl_Box* header_totals_subtotal_box
+      { data_totals_subtotal_box = new Fl_Box(83, 607, 150, 23);
+        data_totals_subtotal_box->box(FL_FLAT_BOX);
+        data_totals_subtotal_box->color(FL_BACKGROUND2_COLOR);
+        data_totals_subtotal_box->labeltype(FL_NO_LABEL);
+        data_totals_subtotal_box->labelfont(1);
+        data_totals_subtotal_box->labelsize(12);
+      } // Fl_Box* data_totals_subtotal_box
+      { header_totals_total_sales_tax1_box = new Fl_Box(234, 586, 120, 20, _tr("Sales Tax I"));
+        header_totals_total_sales_tax1_box->box(FL_FLAT_BOX);
+        header_totals_total_sales_tax1_box->color(FL_DARK1);
+        header_totals_total_sales_tax1_box->labelfont(1);
+        header_totals_total_sales_tax1_box->labelsize(12);
+      } // Fl_Box* header_totals_total_sales_tax1_box
+      { data_totals_total_sales_tax1_box = new Fl_Box(234, 607, 120, 23);
+        data_totals_total_sales_tax1_box->box(FL_FLAT_BOX);
+        data_totals_total_sales_tax1_box->color(FL_BACKGROUND2_COLOR);
+        data_totals_total_sales_tax1_box->labeltype(FL_NO_LABEL);
+        data_totals_total_sales_tax1_box->labelfont(1);
+        data_totals_total_sales_tax1_box->labelsize(12);
+      } // Fl_Box* data_totals_total_sales_tax1_box
+      { header_totals_total_sales_tax2_box = new Fl_Box(355, 586, 115, 20, _tr("Sales Tax II"));
+        header_totals_total_sales_tax2_box->box(FL_FLAT_BOX);
+        header_totals_total_sales_tax2_box->color(FL_DARK1);
+        header_totals_total_sales_tax2_box->labelfont(1);
+        header_totals_total_sales_tax2_box->labelsize(12);
+      } // Fl_Box* header_totals_total_sales_tax2_box
+      { data_totals_total_sales_tax2_box = new Fl_Box(355, 607, 115, 23);
+        data_totals_total_sales_tax2_box->box(FL_FLAT_BOX);
+        data_totals_total_sales_tax2_box->color(FL_BACKGROUND2_COLOR);
+        data_totals_total_sales_tax2_box->labeltype(FL_NO_LABEL);
+        data_totals_total_sales_tax2_box->labelfont(1);
+        data_totals_total_sales_tax2_box->labelsize(12);
+      } // Fl_Box* data_totals_total_sales_tax2_box
+      { header_totals_total_box = new Fl_Box(471, 586, 150, 20, _tr("TOTAL"));
+        header_totals_total_box->box(FL_FLAT_BOX);
+        header_totals_total_box->color(FL_DARK1);
+        header_totals_total_box->labelfont(1);
+        header_totals_total_box->labelsize(12);
+      } // Fl_Box* header_totals_total_box
+      { data_totals_total_box = new Fl_Box(471, 607, 150, 23);
+        data_totals_total_box->box(FL_FLAT_BOX);
+        data_totals_total_box->color(FL_BACKGROUND2_COLOR);
+        data_totals_total_box->labeltype(FL_NO_LABEL);
+        data_totals_total_box->labelfont(1);
+        data_totals_total_box->labelsize(12);
+      } // Fl_Box* data_totals_total_box
+      orderTotals->end();
+    } // Fl_Group* orderTotals
+    { notes_box = new Fl_Box_ClearLabel(17, 638, 606, 37, _tr(@"FLTK is provided under the terms of the GNU Library Public License, Version 2\
+ with exceptions that allow for static linking."));
+      notes_box->box(FL_NO_BOX);
+      notes_box->color(FL_BACKGROUND_COLOR);
+      notes_box->selection_color(FL_BACKGROUND_COLOR);
+      notes_box->labeltype(FL_NORMAL_LABEL);
+      notes_box->labelfont(2);
+      notes_box->labelsize(9);
+      notes_box->labelcolor(FL_FOREGROUND_COLOR);
+      notes_box->align((FL_ALIGN_WRAP|FL_ALIGN_INSIDE));
+      notes_box->when(FL_WHEN_RELEASE);
+    } // Fl_Box_ClearLabel* notes_box
+    pageDesignGroup->end();
+  } // Fl_Group* pageDesignGroup
+  { printDataGroup = new Fl_Group(3, 0, 628, 637);
+    printDataGroup->labeltype(FL_NO_LABEL);
+    { orderTypeBox = new Fl_Box(338, 10, 139, 20);
+      orderTypeBox->labelfont(1);
+      orderTypeBox->labelsize(12);
+    } // Fl_Box* orderTypeBox
+    { numberBox = new Fl_Box_ClearLabel(338, 33, 139, 16);
+      numberBox->box(FL_NO_BOX);
+      numberBox->color(FL_BACKGROUND_COLOR);
+      numberBox->selection_color(FL_BACKGROUND_COLOR);
+      numberBox->labeltype(FL_NORMAL_LABEL);
+      numberBox->labelfont(5);
+      numberBox->labelsize(15);
+      numberBox->labelcolor(FL_FOREGROUND_COLOR);
+      numberBox->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
+      numberBox->when(FL_WHEN_RELEASE);
+    } // Fl_Box_ClearLabel* numberBox
+    { dateBox = new Fl_Box_ClearLabel(484, 32, 133, 16);
+      dateBox->box(FL_NO_BOX);
+      dateBox->color(FL_BACKGROUND_COLOR);
+      dateBox->selection_color(FL_BACKGROUND_COLOR);
+      dateBox->labeltype(FL_NORMAL_LABEL);
+      dateBox->labelfont(5);
+      dateBox->labelsize(15);
+      dateBox->labelcolor(FL_FOREGROUND_COLOR);
+      dateBox->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
+      dateBox->when(FL_WHEN_RELEASE);
+    } // Fl_Box_ClearLabel* dateBox
+    { entityBox = new Fl_Box_ClearLabel(338, 57, 282, 82);
+      entityBox->box(FL_NO_BOX);
+      entityBox->color(FL_BACKGROUND_COLOR);
+      entityBox->selection_color(FL_BACKGROUND_COLOR);
+      entityBox->labeltype(FL_NORMAL_LABEL);
+      entityBox->labelfont(0);
+      entityBox->labelsize(12);
+      entityBox->labelcolor(FL_FOREGROUND_COLOR);
+      entityBox->align((69|FL_ALIGN_INSIDE));
+      entityBox->when(FL_WHEN_RELEASE);
+    } // Fl_Box_ClearLabel* entityBox
+    { dataLinesGroup = new Fl_Group(16, 169, 605, 412);
+      dataLinesGroup->labeltype(FL_NO_LABEL);
+      dataLinesGroup->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
+      { codeBox = new Fl_Box_ClearLabel(16, 174, 46, 404);
+        codeBox->box(FL_NO_BOX);
+        codeBox->color(FL_BACKGROUND_COLOR);
+        codeBox->selection_color(FL_BACKGROUND_COLOR);
+        codeBox->labeltype(FL_NORMAL_LABEL);
+        codeBox->labelfont(0);
+        codeBox->labelsize(11);
+        codeBox->labelcolor(FL_FOREGROUND_COLOR);
+        codeBox->align((FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE));
+        codeBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* codeBox
+      { descriptionBox = new Fl_Box_ClearLabel(64, 174, 300, 404);
+        descriptionBox->box(FL_NO_BOX);
+        descriptionBox->color(FL_BACKGROUND_COLOR);
+        descriptionBox->selection_color(FL_BACKGROUND_COLOR);
+        descriptionBox->labeltype(FL_NORMAL_LABEL);
+        descriptionBox->labelfont(0);
+        descriptionBox->labelsize(11);
+        descriptionBox->labelcolor(FL_FOREGROUND_COLOR);
+        descriptionBox->align((69|FL_ALIGN_INSIDE));
+        descriptionBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* descriptionBox
+      { quantityBox = new Fl_Box_ClearLabel(365, 174, 40, 404);
+        quantityBox->box(FL_NO_BOX);
+        quantityBox->color(FL_BACKGROUND_COLOR);
+        quantityBox->selection_color(FL_BACKGROUND_COLOR);
+        quantityBox->labeltype(FL_NORMAL_LABEL);
+        quantityBox->labelfont(0);
+        quantityBox->labelsize(11);
+        quantityBox->labelcolor(FL_FOREGROUND_COLOR);
+        quantityBox->align((FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE));
+        quantityBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* quantityBox
+      { priceBox = new Fl_Box_ClearLabel(406, 174, 60, 404);
+        priceBox->box(FL_NO_BOX);
+        priceBox->color(FL_BACKGROUND_COLOR);
+        priceBox->selection_color(FL_BACKGROUND_COLOR);
+        priceBox->labeltype(FL_NORMAL_LABEL);
+        priceBox->labelfont(0);
+        priceBox->labelsize(11);
+        priceBox->labelcolor(FL_FOREGROUND_COLOR);
+        priceBox->align((FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE));
+        priceBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* priceBox
+      { discountBox = new Fl_Box_ClearLabel(467, 174, 30, 404);
+        discountBox->box(FL_NO_BOX);
+        discountBox->color(FL_BACKGROUND_COLOR);
+        discountBox->selection_color(FL_BACKGROUND_COLOR);
+        discountBox->labeltype(FL_NORMAL_LABEL);
+        discountBox->labelfont(0);
+        discountBox->labelsize(11);
+        discountBox->labelcolor(FL_FOREGROUND_COLOR);
+        discountBox->align((FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE));
+        discountBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* discountBox
+      { sales_tax1Box = new Fl_Box_ClearLabel(498, 174, 30, 404);
+        sales_tax1Box->box(FL_NO_BOX);
+        sales_tax1Box->color(FL_BACKGROUND_COLOR);
+        sales_tax1Box->selection_color(FL_BACKGROUND_COLOR);
+        sales_tax1Box->labeltype(FL_NORMAL_LABEL);
+        sales_tax1Box->labelfont(0);
+        sales_tax1Box->labelsize(11);
+        sales_tax1Box->labelcolor(FL_FOREGROUND_COLOR);
+        sales_tax1Box->align((FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE));
+        sales_tax1Box->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* sales_tax1Box
+      { sales_tax2Box = new Fl_Box_ClearLabel(529, 174, 30, 404);
+        sales_tax2Box->box(FL_NO_BOX);
+        sales_tax2Box->color(FL_BACKGROUND_COLOR);
+        sales_tax2Box->selection_color(FL_BACKGROUND_COLOR);
+        sales_tax2Box->labeltype(FL_NORMAL_LABEL);
+        sales_tax2Box->labelfont(0);
+        sales_tax2Box->labelsize(11);
+        sales_tax2Box->labelcolor(FL_FOREGROUND_COLOR);
+        sales_tax2Box->align((FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE));
+        sales_tax2Box->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* sales_tax2Box
+      { lineTotalBox = new Fl_Box_ClearLabel(560, 174, 61, 404);
+        lineTotalBox->box(FL_NO_BOX);
+        lineTotalBox->color(FL_BACKGROUND_COLOR);
+        lineTotalBox->selection_color(FL_BACKGROUND_COLOR);
+        lineTotalBox->labeltype(FL_NORMAL_LABEL);
+        lineTotalBox->labelfont(0);
+        lineTotalBox->labelsize(11);
+        lineTotalBox->labelcolor(FL_FOREGROUND_COLOR);
+        lineTotalBox->align((FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE));
+        lineTotalBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* lineTotalBox
+      dataLinesGroup->end();
+      Fl_Group.current()->resizable(dataLinesGroup);
+    } // Fl_Group* dataLinesGroup
+    { bottomTotals = new Fl_Group(16, 585, 605, 48);
+      bottomTotals->labeltype(FL_NO_LABEL);
+      { orderPageBox = new Fl_Box_ClearLabel(16, 608, 65, 25);
+        orderPageBox->box(FL_NO_BOX);
+        orderPageBox->color(FL_BACKGROUND_COLOR);
+        orderPageBox->selection_color(FL_BACKGROUND_COLOR);
+        orderPageBox->labeltype(FL_NORMAL_LABEL);
+        orderPageBox->labelfont(5);
+        orderPageBox->labelsize(15);
+        orderPageBox->labelcolor(FL_FOREGROUND_COLOR);
+        orderPageBox->align((FL_ALIGN_CENTER));
+        orderPageBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* orderPageBox
+      { fisrtTotalBox = new Fl_Box_ClearLabel(83, 608, 150, 25);
+        fisrtTotalBox->box(FL_NO_BOX);
+        fisrtTotalBox->color(FL_BACKGROUND_COLOR);
+        fisrtTotalBox->selection_color(FL_BACKGROUND_COLOR);
+        fisrtTotalBox->labeltype(FL_NORMAL_LABEL);
+        fisrtTotalBox->labelfont(5);
+        fisrtTotalBox->labelsize(15);
+        fisrtTotalBox->labelcolor(FL_FOREGROUND_COLOR);
+        fisrtTotalBox->align((FL_ALIGN_CENTER));
+        fisrtTotalBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* fisrtTotalBox
+      { sales_tax1AmountBox = new Fl_Box_ClearLabel(234, 608, 120, 25);
+        sales_tax1AmountBox->box(FL_NO_BOX);
+        sales_tax1AmountBox->color(FL_BACKGROUND_COLOR);
+        sales_tax1AmountBox->selection_color(FL_BACKGROUND_COLOR);
+        sales_tax1AmountBox->labeltype(FL_NORMAL_LABEL);
+        sales_tax1AmountBox->labelfont(5);
+        sales_tax1AmountBox->labelsize(15);
+        sales_tax1AmountBox->labelcolor(FL_FOREGROUND_COLOR);
+        sales_tax1AmountBox->align((FL_ALIGN_CENTER));
+        sales_tax1AmountBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* sales_tax1AmountBox
+      { sales_tax2AmountBox = new Fl_Box_ClearLabel(355, 608, 115, 25);
+        sales_tax2AmountBox->box(FL_NO_BOX);
+        sales_tax2AmountBox->color(FL_BACKGROUND_COLOR);
+        sales_tax2AmountBox->selection_color(FL_BACKGROUND_COLOR);
+        sales_tax2AmountBox->labeltype(FL_NORMAL_LABEL);
+        sales_tax2AmountBox->labelfont(5);
+        sales_tax2AmountBox->labelsize(15);
+        sales_tax2AmountBox->labelcolor(FL_FOREGROUND_COLOR);
+        sales_tax2AmountBox->align((FL_ALIGN_CENTER));
+        sales_tax2AmountBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* sales_tax2AmountBox
+      { totalBox = new Fl_Box_ClearLabel(500, 608, 121, 25);
+        totalBox->box(FL_NO_BOX);
+        totalBox->color(FL_BACKGROUND_COLOR);
+        totalBox->selection_color(FL_BACKGROUND_COLOR);
+        totalBox->labeltype(FL_NORMAL_LABEL);
+        totalBox->labelfont(5);
+        totalBox->labelsize(15);
+        totalBox->labelcolor(FL_FOREGROUND_COLOR);
+        totalBox->align((FL_ALIGN_CENTER));
+        totalBox->when(FL_WHEN_RELEASE);
+      } // Fl_Box_ClearLabel* totalBox
+      bottomTotals->end();
+    } // Fl_Group* bottomTotals
+    printDataGroup->end();
+    Fl_Group.current()->resizable(printDataGroup);
+  } // Fl_Group* printDataGroup
+  page->end();
+} // Fl_Group* page
+end();
+resizable(this);
+}
+}

+ 89 - 0
ourbiz/list-search-gui.fl

@@ -0,0 +1,89 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.0300 
+i18n_type 1 
+i18n_include i18n_function.h 
+i18n_function _tr 
+header_name {.h} 
+code_name {.cxx}
+decl {\#include "My_Base_App.h"} {public global
+} 
+
+widget_class ListSearchWindow {
+  label {List Search} open
+  xywh {132 118 800 560} type Double labelsize 16 resizable
+  class List_Search_Base_Window visible
+} {
+  Fl_Group topGroup {open
+    xywh {0 0 800 35} labelsize 16
+  } {
+    Fl_Input group_filter {
+      dirty_name {@group_filter} selected
+      xywh {5 5 675 25} labeltype NO_LABEL labelsize 16 textsize 16
+      class Flu_Combo_Box
+    }
+    Fl_Input query_limit {
+      xywh {690 6 60 25} type Int labeltype NO_LABEL labelsize 16 textsize 16
+      code0 {o->value("50");}
+    }
+    Fl_Button btnNotes {
+      label {?}
+      xywh {760 6 35 25} labelsize 16
+    }
+  }
+  Fl_Group middleGroup {open
+    xywh {0 41 800 409} labelsize 16 resizable
+  } {
+    Fl_Browser grid {
+      dirty_name {@grid}
+      xywh {5 41 790 389} type Multi labeltype NO_LABEL labelsize 16 textsize 16 resizable
+      class Fl_Data_Table
+    }
+  }
+  Fl_Group bottomGroup {open
+    xywh {4 440 790 115} box ENGRAVED_BOX color 246 labelsize 16
+  } {
+    Fl_Pack pack_search_options {open
+      xywh {14 450 320 25} type HORIZONTAL labelsize 16
+      code0 {o->spacing(10);}
+    } {}
+    Fl_Input search_str {
+      label {@search}
+      callback {on_search();}
+      dirty_name {@search_str}
+      xywh {35 485 299 25} labelsize 16 when 8 textsize 16
+    }
+    Fl_Button btnSearch {
+      label Search
+      callback {on_search();}
+      xywh {345 485 100 25} labelsize 16
+    }
+    Fl_Button btnSelect {
+      label Select
+      callback {on_select();}
+      xywh {14 520 100 25} labelsize 16
+    }
+    Fl_Button btnUpdate {
+      label Update
+      callback {on_update();}
+      xywh {124 520 100 25} labelsize 16
+    }
+    Fl_Button btnInsert {
+      label Insert
+      callback {on_insert();}
+      xywh {234 520 100 25} labelsize 16
+    }
+    Fl_Button btnThumbImage {
+      xywh {663 445 125 105} box NO_BOX align 80
+      class Fl_Image_Box
+    }
+    Fl_Box {} {
+      xywh {650 445 5 105} labeltype NO_LABEL labelsize 16 align 80 resizable
+    }
+    Fl_Pack pack_search_options2 {open
+      xywh {345 520 300 25} type HORIZONTAL labelsize 16
+      code0 {o->spacing(10);}
+    } {}
+  }
+  code {group_filter->textfont(group_filter->labelfont());
+group_filter->textsize(group_filter->labelsize());} {}
+} 

+ 263 - 0
ourbiz/list-search-window.nut

@@ -0,0 +1,263 @@
+class Fl_Data_Table extends Flv_Table {
+	_forPrint = null;
+	
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+		_forPrint=false;
+	}
+}
+
+class Fl_Box_ClearLabel extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Flu_Combo_List extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Image_Box extends Fl_Box {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+class Fl_Choice_Int extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Float_Input_Fmt extends Fl_Float_Input {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class My_Fl_Float_Input extends Fl_Float_Input {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+class My_Fl_Return_Button extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Fl_Choice_Str extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+class Flu_Combo_Box extends Fl_Button {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+
+function add_input_field_to_map(tbl, fldname, fld){
+}
+	
+//class BaseReportA4 extends Fl_Group {
+class ListSearch extends MyBaseWindow {
+	topGroup=null;
+	group_filter=null;
+	query_limit=null;
+	btnNotes=null;
+	middleGroup=null;
+	grid=null;
+	bottomGroup=null;
+	pack_search_options=null;
+	search_str=null;
+	btnSearch=null;
+	btnSelect=null;
+	btnUpdate=null;
+	btnInsert=null;
+	btnThumbImage=null;
+	pack_search_options2=null;
+
+constructor() {
+	base.constructor(10, 50, 800, 560, _tr("List Search"));
+begin();
+this->box(FL_FLAT_BOX);
+this->color(FL_BACKGROUND_COLOR);
+this->selection_color(FL_BACKGROUND_COLOR);
+this->labeltype(FL_NO_LABEL);
+this->labelfont(0);
+this->labelsize(16);
+this->labelcolor(FL_FOREGROUND_COLOR);
+this->align((FL_ALIGN_TOP));
+this->when(FL_WHEN_RELEASE);
+{ topGroup = new Fl_Group(0, 0, 800, 35);
+  topGroup->labelsize(16);
+  { group_filter = new Flu_Combo_Box(5, 5, 675, 25);
+    group_filter->resize(5, 5, 675, 25);
+    group_filter->box(FL_DOWN_BOX);
+    group_filter->color(FL_BACKGROUND2_COLOR);
+    group_filter->selection_color(FL_SELECTION_COLOR);
+    group_filter->labeltype(FL_NO_LABEL);
+    group_filter->labelfont(0);
+    group_filter->labelsize(16);
+    group_filter->labelcolor(FL_FOREGROUND_COLOR);
+    group_filter->textsize(16);
+    group_filter->align((FL_ALIGN_LEFT));
+    group_filter->when(FL_WHEN_RELEASE);
+  } // Flu_Combo_Box* group_filter
+  { local o = query_limit = new Fl_Int_Input(690, 6, 60, 25);
+    query_limit->type(2);
+    query_limit->labeltype(FL_NO_LABEL);
+    query_limit->labelsize(16);
+    query_limit->textsize(16);
+    o->value("50");
+  } // Fl_Int_Input* query_limit
+  { btnNotes = new Fl_Button(760, 6, 35, 25, _tr("?"));
+    btnNotes->labelsize(16);
+  } // Fl_Button* btnNotes
+  topGroup->end();
+} // Fl_Group* topGroup
+{ middleGroup = new Fl_Group(0, 41, 800, 409);
+  middleGroup->labelsize(16);
+  { grid = new Fl_Data_Table(5, 41, 790, 389);
+    grid->resize(5, 41, 790, 389);
+    grid->type(3);
+    grid->box(FL_NO_BOX);
+    grid->color(FL_BACKGROUND2_COLOR);
+    grid->selection_color(FL_SELECTION_COLOR);
+    grid->labeltype(FL_NO_LABEL);
+    grid->labelfont(0);
+    grid->labelsize(16);
+    grid->labelcolor(FL_FOREGROUND_COLOR);
+    grid->textsize(16);
+    grid->align((FL_ALIGN_BOTTOM));
+    grid->when(FL_WHEN_RELEASE_ALWAYS);
+    Fl_Group.current()->resizable(grid);
+  } // Fl_Data_Table* grid
+  middleGroup->end();
+  Fl_Group.current()->resizable(middleGroup);
+} // Fl_Group* middleGroup
+{ bottomGroup = new Fl_Group(4, 440, 790, 115);
+  bottomGroup->box(FL_ENGRAVED_BOX);
+  bottomGroup->color(246);
+  bottomGroup->labelsize(16);
+  { local o = pack_search_options = new Fl_Pack(14, 450, 320, 25);
+    pack_search_options->type(1);
+    pack_search_options->labelsize(16);
+    o->spacing(10);
+    pack_search_options->end();
+  } // Fl_Pack* pack_search_options
+  { search_str = new Fl_Input(35, 485, 299, 25, _tr("@search"));
+    search_str->resize(35, 485, 299, 25);
+    search_str->label(_tr("@search"));
+    search_str->labelsize(16);
+    search_str->textsize(16);
+    search_str->callback(cb_search_str);
+    search_str->when(FL_WHEN_ENTER_KEY);
+  } // Fl_Input* search_str
+  { btnSearch = new Fl_Button(345, 485, 100, 25, _tr("Search"));
+    btnSearch->labelsize(16);
+    btnSearch->callback(cb_btnSearch);
+  } // Fl_Button* btnSearch
+  { btnSelect = new Fl_Button(14, 520, 100, 25, _tr("Select"));
+    btnSelect->labelsize(16);
+    btnSelect->callback(cb_btnSelect);
+  } // Fl_Button* btnSelect
+  { btnUpdate = new Fl_Button(124, 520, 100, 25, _tr("Update"));
+    btnUpdate->labelsize(16);
+    btnUpdate->callback(cb_btnUpdate);
+  } // Fl_Button* btnUpdate
+  { btnInsert = new Fl_Button(234, 520, 100, 25, _tr("Insert"));
+    btnInsert->labelsize(16);
+    btnInsert->callback(cb_btnInsert);
+  } // Fl_Button* btnInsert
+  { btnThumbImage = new Fl_Image_Box(663, 445, 125, 105);
+    btnThumbImage->box(FL_NO_BOX);
+    btnThumbImage->color(FL_BACKGROUND_COLOR);
+    btnThumbImage->selection_color(FL_BACKGROUND_COLOR);
+    btnThumbImage->labeltype(FL_NORMAL_LABEL);
+    btnThumbImage->labelfont(0);
+    btnThumbImage->labelsize(14);
+    btnThumbImage->labelcolor(FL_FOREGROUND_COLOR);
+    btnThumbImage->align((FL_ALIGN_CLIP|FL_ALIGN_INSIDE));
+    btnThumbImage->when(FL_WHEN_RELEASE);
+  } // Fl_Image_Box* btnThumbImage
+  { local o = new Fl_Box(650, 445, 5, 105);
+    o->labeltype(FL_NO_LABEL);
+    o->labelsize(16);
+    o->align((FL_ALIGN_CLIP|FL_ALIGN_INSIDE));
+    Fl_Group.current()->resizable(o);
+  } // Fl_Box* o
+  { local o = pack_search_options2 = new Fl_Pack(345, 520, 300, 25);
+    pack_search_options2->type(1);
+    pack_search_options2->labelsize(16);
+    o->spacing(10);
+    pack_search_options2->end();
+  } // Fl_Pack* pack_search_options2
+  bottomGroup->end();
+} // Fl_Group* bottomGroup
+group_filter->textfont(group_filter->labelfont());
+group_filter->textsize(group_filter->labelsize());
+end();
+}
+
+function cb_search_str(){}
+function cb_btnSearch(){}
+function cb_btnSelect(){}
+function cb_btnUpdate(){}
+function cb_btnInsert(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Order Edit", EditOrderWindow);
+}
+}
+
+class EntitiesListSearch extends ListSearch {
+
+	constructor() {
+		base.constructor();
+		label(_tr("Entities List Search"));
+	}
+	function cb_btnInsert(sender, udata){
+		local pr = sender.parent_root();
+		local win = pr.showChildWindow("Entity Edit", EditEntitiesWindow);
+	}
+}
+
+class ProductsListSearch extends ListSearch {
+
+	constructor() {
+		base.constructor();
+		label(_tr("Products List Search"));
+	}
+	function cb_btnInsert(sender, udata){
+		local pr = sender.parent_root();
+		local win = pr.showChildWindow("Product Edit", EditProductWindow);
+	}
+}
+
+class OrdersListSearch extends ListSearch {
+
+	constructor() {
+		base.constructor();
+		label(_tr("Orders List Search"));
+	}
+	function cb_btnInsert(sender, udata){
+		local pr = sender.parent_root();
+		local win = pr.showChildWindow("Order Edit", EditOrderWindow);
+	}
+}
+
+class PaymentsListSearch extends ListSearch {
+
+	constructor() {
+		base.constructor();
+		label(_tr("Payments List Search"));
+	}
+}

+ 337 - 0
ourbiz/main-window.nut

@@ -0,0 +1,337 @@
+class MainWindow extends MyBaseWindow {
+	tabs=null;
+	tabSales=null;
+	btnOrdersSales=null;
+	btnPaymentsSales=null;
+	btnEntitiesSales=null;
+	btnProductsSales=null;
+	tabBuys=null;
+	btnOrdersBuys=null;
+	btnPaymentsBuys=null;
+	btnProductsBuys=null;
+	btnEntitiesBuys=null;
+	tabAll=null;
+	btnOrders=null;
+	btnPayments=null;
+	btnEntities=null;
+	btnProducts=null;
+	tabGL=null;
+	btnGLGroups=null;
+	btnGLChart=null;
+	btnGLTransactions=null;
+	tabConfig=null;
+	config_scroll=null;
+	config_pack=null;
+	btnOrdersSum=null;
+	btnSalesTaxRates=null;
+	btnOrderTypes=null;
+	btnPaymentTypes=null;
+	btnMeasureUnits=null;
+	btnWarrantyTypes=null;
+	btnImages=null;
+	btnProductGroups=null;
+	btnEntityGroups=null;
+	btnConfig=null;
+	btnOpenDB=null;
+	btnTranslations=null;
+	btnAppUsers=null;
+	btnAskForPrinter=null;
+	btnWebServer=null;
+
+constructor(px, py, pw, ph, pl) {
+	base.constructor(px, py, pw, ph, pl);
+	begin();
+	this->box(FL_FLAT_BOX);
+	this->color(FL_BACKGROUND_COLOR);
+	this->selection_color(FL_BACKGROUND_COLOR);
+	this->labeltype(FL_NO_LABEL);
+	this->labelfont(0);
+	this->labelsize(16);
+	this->labelcolor(FL_FOREGROUND_COLOR);
+	this->align(FL_ALIGN_TOP);
+	this->when(FL_WHEN_RELEASE);
+	reset_all_child_windows_ptr();
+	{ tabs = new Fl_Tabs(5, 5, 320, 310);
+	  tabs->selection_color(4);
+	  tabs->labelsize(16);
+	  tabs->labelcolor(FL_BACKGROUND2_COLOR);
+	  { tabSales = new Fl_Group(5, 35, 320, 280, _tr("Sales"));
+	    tabSales->color(127);
+	    tabSales->labelsize(16);
+	    { btnOrdersSales = new Fl_Button(30, 50, 275, 55, _tr("Sales"));
+	      btnOrdersSales->labeltype(FL_SHADOW_LABEL);
+	      btnOrdersSales->labelfont(3);
+	      btnOrdersSales->labelsize(34);
+	      btnOrdersSales->labelcolor(FL_INACTIVE_COLOR);
+	      btnOrdersSales->callback(cb_btnOrdersSales);
+	      btnOrdersSales->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
+	    } // Fl_Button* btnOrdersSales
+	    { btnPaymentsSales = new Fl_Button(30, 116, 275, 55, _tr("Payments"));
+	      btnPaymentsSales->labeltype(FL_SHADOW_LABEL);
+	      btnPaymentsSales->labelfont(3);
+	      btnPaymentsSales->labelsize(34);
+	      btnPaymentsSales->labelcolor(FL_INACTIVE_COLOR);
+	      btnPaymentsSales->callback(cb_btnPaymentsSales);
+	    } // Fl_Button* btnPaymentsSales
+	    { btnEntitiesSales = new Fl_Button(30, 183, 275, 55, _tr("Customers"));
+	      btnEntitiesSales->labeltype(FL_SHADOW_LABEL);
+	      btnEntitiesSales->labelfont(3);
+	      btnEntitiesSales->labelsize(34);
+	      btnEntitiesSales->labelcolor(FL_INACTIVE_COLOR);
+	      btnEntitiesSales->callback(cb_btnEntitiesSales);
+	    } // Fl_Button* btnEntitiesSales
+	    { btnProductsSales = new Fl_Button(30, 250, 275, 55, _tr("Products"));
+	      btnProductsSales->labeltype(FL_SHADOW_LABEL);
+	      btnProductsSales->labelfont(3);
+	      btnProductsSales->labelsize(34);
+	      btnProductsSales->labelcolor(FL_INACTIVE_COLOR);
+	      btnProductsSales->callback(cb_btnProductsSales);
+	    } // Fl_Button* btnProductsSales
+	    tabSales->end();
+	  } // Fl_Group* tabSales
+	  { tabBuys = new Fl_Group(5, 35, 320, 280, _tr("Buys"));
+	    tabBuys->color(174);
+	    tabBuys->labelsize(16);
+	    tabBuys->hide();
+	    { btnOrdersBuys = new Fl_Button(30, 50, 275, 55, _tr("Buys"));
+	      btnOrdersBuys->labeltype(FL_SHADOW_LABEL);
+	      btnOrdersBuys->labelfont(3);
+	      btnOrdersBuys->labelsize(34);
+	      btnOrdersBuys->labelcolor(FL_INACTIVE_COLOR);
+	      btnOrdersBuys->callback(cb_btnOrdersBuys);
+	      btnOrdersBuys->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
+	    } // Fl_Button* btnOrdersBuys
+	    { btnPaymentsBuys = new Fl_Button(30, 115, 275, 55, _tr("Payments"));
+	      btnPaymentsBuys->labeltype(FL_SHADOW_LABEL);
+	      btnPaymentsBuys->labelfont(3);
+	      btnPaymentsBuys->labelsize(34);
+	      btnPaymentsBuys->labelcolor(FL_INACTIVE_COLOR);
+	      btnPaymentsBuys->callback(cb_btnPaymentsBuys);
+	    } // Fl_Button* btnPaymentsBuys
+	    { btnProductsBuys = new Fl_Button(30, 250, 275, 55, _tr("Products"));
+	      btnProductsBuys->labeltype(FL_SHADOW_LABEL);
+	      btnProductsBuys->labelfont(3);
+	      btnProductsBuys->labelsize(34);
+	      btnProductsBuys->labelcolor(FL_INACTIVE_COLOR);
+	      btnProductsBuys->callback(cb_btnProductsBuys);
+	    } // Fl_Button* btnProductsBuys
+	    { btnEntitiesBuys = new Fl_Button(30, 183, 275, 55, _tr("Suppliers"));
+	      btnEntitiesBuys->labeltype(FL_SHADOW_LABEL);
+	      btnEntitiesBuys->labelfont(3);
+	      btnEntitiesBuys->labelsize(34);
+	      btnEntitiesBuys->labelcolor(FL_INACTIVE_COLOR);
+	      btnEntitiesBuys->callback(cb_btnEntitiesBuys);
+	    } // Fl_Button* btnEntitiesBuys
+	    tabBuys->end();
+	  } // Fl_Group* tabBuys
+	  { tabAll = new Fl_Group(5, 35, 320, 280, _tr("All"));
+	    tabAll->color(239);
+	    tabAll->labelsize(16);
+	    tabAll->hide();
+	    { btnOrders = new Fl_Button(30, 50, 275, 55, _tr("Orders"));
+	      btnOrders->labeltype(FL_SHADOW_LABEL);
+	      btnOrders->labelfont(3);
+	      btnOrders->labelsize(34);
+	      btnOrders->labelcolor(FL_INACTIVE_COLOR);
+	      btnOrders->callback(cb_btnOrders);
+	      btnOrders->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
+	    } // Fl_Button* btnOrders
+	    { btnPayments = new Fl_Button(30, 116, 275, 55, _tr("Payments"));
+	      btnPayments->labeltype(FL_SHADOW_LABEL);
+	      btnPayments->labelfont(3);
+	      btnPayments->labelsize(34);
+	      btnPayments->labelcolor(FL_INACTIVE_COLOR);
+	      btnPayments->callback(cb_btnPayments);
+	    } // Fl_Button* btnPayments
+	    { btnEntities = new Fl_Button(30, 183, 275, 55, _tr("Entities"));
+	      btnEntities->labeltype(FL_SHADOW_LABEL);
+	      btnEntities->labelfont(3);
+	      btnEntities->labelsize(34);
+	      btnEntities->labelcolor(FL_INACTIVE_COLOR);
+	      btnEntities->callback(cb_btnEntities);
+	    } // Fl_Button* btnEntities
+	    { btnProducts = new Fl_Button(30, 250, 275, 55, _tr("Products"));
+	      btnProducts->labeltype(FL_SHADOW_LABEL);
+	      btnProducts->labelfont(3);
+	      btnProducts->labelsize(34);
+	      btnProducts->labelcolor(FL_INACTIVE_COLOR);
+	      btnProducts->callback(cb_btnProducts);
+	    } // Fl_Button* btnProducts
+	    tabAll->end();
+	    Fl_Group.current()->resizable(tabAll);
+	  } // Fl_Group* tabAll
+	  { tabGL = new Fl_Group(5, 35, 320, 280, _tr("GL"));
+	    tabGL->color(132);
+	    tabGL->labelsize(16);
+	    tabGL->hide();
+	    { btnGLGroups = new Fl_Button(30, 50, 275, 55, _tr("Groups"));
+	      btnGLGroups->labeltype(FL_SHADOW_LABEL);
+	      btnGLGroups->labelfont(3);
+	      btnGLGroups->labelsize(34);
+	      btnGLGroups->labelcolor(FL_INACTIVE_COLOR);
+	      btnGLGroups->callback(cb_btnGLGroups);
+	      btnGLGroups->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
+	    } // Fl_Button* btnGLGroups
+	    { btnGLChart = new Fl_Button(30, 115, 275, 55, _tr("Chart"));
+	      btnGLChart->labeltype(FL_SHADOW_LABEL);
+	      btnGLChart->labelfont(3);
+	      btnGLChart->labelsize(34);
+	      btnGLChart->labelcolor(FL_INACTIVE_COLOR);
+	      btnGLChart->callback(cb_btnGLChart);
+	    } // Fl_Button* btnGLChart
+	    { btnGLTransactions = new Fl_Button(30, 180, 275, 55, _tr("Transactions"));
+	      btnGLTransactions->labeltype(FL_SHADOW_LABEL);
+	      btnGLTransactions->labelfont(3);
+	      btnGLTransactions->labelsize(34);
+	      btnGLTransactions->labelcolor(FL_INACTIVE_COLOR);
+	      btnGLTransactions->callback(cb_btnGLTransactions);
+	    } // Fl_Button* btnGLTransactions
+	    tabGL->end();
+	  } // Fl_Group* tabGL
+	  { tabConfig = new Fl_Group(5, 35, 320, 280, _tr("Config"));
+	    tabConfig->labelsize(16);
+	    tabConfig->hide();
+	    { config_scroll = new Fl_Scroll(10, 45, 310, 265);
+	      config_scroll->labelsize(16);
+	      { local o = config_pack = new Fl_Pack(30, 45, 270, 260);
+		config_pack->labelsize(16);
+		{ btnOrdersSum = new Fl_Button(65, 55, 64, 30, _tr("Orders Sum"));
+		  btnOrdersSum->labelsize(16);
+		  btnOrdersSum->callback(cb_btnOrdersSum);
+		} // Fl_Button* btnOrdersSum
+		{ btnSalesTaxRates = new Fl_Button(55, 45, 64, 30, _tr("Sales Tax Rates"));
+		  btnSalesTaxRates->labelsize(16);
+		  btnSalesTaxRates->callback(cb_btnSalesTaxRates);
+		} // Fl_Button* btnSalesTaxRates
+		{ btnOrderTypes = new Fl_Button(65, 80, 64, 30, _tr("Order Types"));
+		  btnOrderTypes->labelsize(16);
+		  btnOrderTypes->callback(cb_btnOrderTypes);
+		} // Fl_Button* btnOrderTypes
+		{ btnPaymentTypes = new Fl_Button(105, 148, 64, 30, _tr("Payment Types"));
+		  btnPaymentTypes->labelsize(16);
+		  btnPaymentTypes->callback(cb_btnPaymentTypes);
+		} // Fl_Button* btnPaymentTypes
+		{ btnMeasureUnits = new Fl_Button(115, 158, 64, 30, _tr("Measure Units"));
+		  btnMeasureUnits->labelsize(16);
+		  btnMeasureUnits->callback(cb_btnMeasureUnits);
+		} // Fl_Button* btnMeasureUnits
+		{ btnWarrantyTypes = new Fl_Button(125, 168, 64, 30, _tr("Warranty Types"));
+		  btnWarrantyTypes->labelsize(16);
+		  btnWarrantyTypes->callback(cb_btnWarrantyTypes);
+		} // Fl_Button* btnWarrantyTypes
+		{ btnImages = new Fl_Button(75, 118, 64, 30, _tr("Images"));
+		  btnImages->labelsize(16);
+		  btnImages->callback(cb_btnImages);
+		} // Fl_Button* btnImages
+		{ btnProductGroups = new Fl_Button(85, 128, 64, 30, _tr("Product Groups"));
+		  btnProductGroups->labelsize(16);
+		  btnProductGroups->callback(cb_btnProductGroups);
+		} // Fl_Button* btnProductGroups
+		{ btnEntityGroups = new Fl_Button(95, 138, 64, 30, _tr("Entity Groups"));
+		  btnEntityGroups->labelsize(16);
+		  btnEntityGroups->callback(cb_btnEntityGroups);
+		} // Fl_Button* btnEntityGroups
+		{ btnConfig = new Fl_Button(105, 148, 64, 30, _tr("App Config"));
+		  btnConfig->labelsize(16);
+		  btnConfig->callback(cb_btnConfig);
+		} // Fl_Button* btnConfig
+		{ btnOpenDB = new Fl_Button(115, 158, 64, 30, _tr("Open Database"));
+		  btnOpenDB->tooltip(_tr("Open a database file"));
+		  btnOpenDB->labelsize(16);
+		  btnOpenDB->callback(cb_btnOpenDB);
+		} // Fl_Button* btnOpenDB
+		{ btnTranslations = new Fl_Button(115, 158, 64, 30, _tr("Translations"));
+		  btnTranslations->labelsize(16);
+		  btnTranslations->callback(cb_btnTranslations);
+		} // Fl_Button* btnTranslations
+		{ btnAppUsers = new Fl_Button(75, 65, 64, 30, _tr("App Users"));
+		  btnAppUsers->labelsize(16);
+		  btnAppUsers->callback(cb_btnAppUsers);
+		} // Fl_Button* btnAppUsers
+		{ btnAskForPrinter = new Fl_Check_Button(55, 70, 64, 15, _tr("Ask for Printer"));
+		  btnAskForPrinter->down_box(FL_DOWN_BOX);
+		} // Fl_Check_Button* btnAskForPrinter
+		{ btnWebServer = new Fl_Check_Button(65, 80, 64, 15, _tr("Web Server"));
+		  btnWebServer->down_box(FL_DOWN_BOX);
+		} // Fl_Check_Button* btnWebServer
+		o->spacing(5);
+		config_pack->end();
+	      } // Fl_Pack* config_pack
+	      config_scroll->end();
+	    } // Fl_Scroll* config_scroll
+	    tabConfig->end();
+	  } // Fl_Group* tabConfig
+	  tabs->end();
+	} // Fl_Tabs* tabs
+	end();
+}
+
+function cb_btnEntitiesSales(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Entities Sales List/Search", EntitiesListSearch);
+}
+function cb_btnPaymentsSales(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Payments Sales List/Search", PaymentsListSearch);
+}
+function cb_btnOrdersSales(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Orders Sales List/Search", OrdersListSearch);
+}
+function cb_btnProductsSales(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Products Sales List/Search", ProductsListSearch);
+}
+function cb_btnOrdersBuys(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Orders Buys List/Search", OrdersListSearch);
+}
+function cb_btnPaymentsBuys(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Payments Buys List/Search", PaymentsListSearch);
+}
+function cb_btnProductsBuys(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Products Buys List/Search", ProductsListSearch);
+}
+function cb_btnEntitiesBuys(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Entities Buys List/Search", EntitiesListSearch);
+}
+function cb_btnOrders(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Orders List/Search", OrdersListSearch);
+}
+function cb_btnPayments(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Payments List/Search", PaymentsListSearch);
+}
+function cb_btnEntities(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Entities List/Search", EntitiesListSearch);
+}
+function cb_btnProducts(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Products List/Search", ProductsListSearch);
+}
+function cb_btnGLGroups(){print(__LINE__);}
+function cb_btnGLChart(){print(__LINE__);}
+function cb_btnGLTransactions(){print(__LINE__);}
+function cb_btnOrdersSum(){print(__LINE__);}
+function cb_btnSalesTaxRates(sender, udata){
+	local pr = sender.parent_root();
+	local win = pr.showChildWindow("Sales Tax Rates List/Edit", SalesTaxRatesEditWindow);
+}
+function cb_btnOrderTypes(){print(__LINE__);}
+function cb_btnPaymentTypes(){print(__LINE__);}
+function cb_btnMeasureUnits(){print(__LINE__);}
+function cb_btnWarrantyTypes(){print(__LINE__);}
+function cb_btnImages(){print(__LINE__);}
+function cb_btnProductGroups(){print(__LINE__);}
+function cb_btnEntityGroups(){print(__LINE__);}
+function cb_btnConfig(){print(__LINE__);}
+function cb_btnOpenDB(){print(__LINE__);}
+function cb_btnTranslations(){print(__LINE__);}
+function cb_btnAppUsers(){print(__LINE__);}
+function reset_all_child_windows_ptr(){print(__LINE__);}
+}

+ 693 - 0
ourbiz/ourbiz-client.nut

@@ -0,0 +1,693 @@
+class AuthDigest {
+	_nc = null;
+	_cnonce = null;
+	_username = null;
+	_password = null;
+	_authenticate = null;
+	_realm = null;
+	_qop = null;
+	_nonce = null;
+	_opaque = null;
+	
+	constructor(username =null, password = null){
+		_nc = 0;
+		_cnonce = os.time();
+		credentials(username, password);
+	}
+	function credentials(username, password){
+		_username = username;
+		_password = password;
+	}
+	function okToAuthDigest(){
+		return _authenticate && _authenticate.len() > 0;
+	}
+	function auth_digest(method, uri){
+		if(!okToAuthDigest()) throw "Trying to auth digest without authentication.";
+		local ha1, ha2, ha, ncbuf;
+		ncbuf = format("%08x", ++_nc);
+		local cnoncebuf = format("%012d", ++_cnonce);
+		local _sep = ":";
+		ha1 = md5(_username, _sep, _realm, _sep, _password);
+		ha2 = md5(method, _sep, uri);
+		ha = md5(ha1, _sep, _nonce, _sep, ncbuf, _sep, cnoncebuf, _sep, _qop, _sep, ha2);
+		local result = format([==[
+Digest username="%s", realm="%s", nonce="%s", uri="%s", qop="%s", nc="%s", cnonce="%s", response="%s"]==], _username, _realm, _nonce, uri, _qop, ncbuf, cnoncebuf, ha);
+		if(_opaque && _opaque.len()){
+			result = format("%s, opaque=\"%s\"", result, _opaque);
+		}
+		return result;
+	}
+
+	function parse_authenticate(szAuthenticate){
+		_authenticate = szAuthenticate;
+		_realm = null;
+		_qop = null;
+		_nonce = null;
+		_opaque = null;
+		local function checkKV(k,v){
+			if(v[0] == '"') v = v.slice(1, -2);
+			if(k == "realm") _realm = v;
+			else if(k == "qop") _qop = v;
+			else if(k == "nonce") _nonce = v;
+			else if(k == "opaque") _opaque = v;
+			return true;
+		}
+		checkKV.setenv(this);
+		szAuthenticate.gmatch("(%w+)%s*=%s*(%S+),", checkKV);
+		printf("%s, %s, %s, %s\n", _realm || "?", _qop || "?", _nonce || "?", _opaque || "?");
+	}
+}
+
+//local auth = AuthDigest();
+//auth.parse_authenticate([==[Digest username="mingote", realm="ourbiz.dadbiz.es", nonce="7f1de29e6da19d22b51c68001e7e0e54", uri="/DB/GetList?list=sales_tax_rates", response="08cfa598e5945d3aada09308017da216", qop=auth, nc=00000002, cnonce="bf5f336c1827bbb2"]==]);
+
+
+// HTTP status codes
+enum HTTP_status_code {
+	// 1xx informational
+	CONTINUE = 100,
+	SWITCHING_PROTOCOLS = 101,
+	PROCESSING = 102,
+
+	// 2xx successful
+	OK = 200,
+	CREATED = 201,
+	ACCEPTED = 202,
+	NON_AUTHORITATIVE_INFORMATION = 203,
+	NO_CONTENT = 204,
+	RESET_CONTENT = 205,
+	PARTIAL_CONTENT = 206,
+	MULTI_STATUS = 207,
+	IM_USED = 226,
+
+	// 3xx redirection
+	MULTIPLE_CHOICES = 300,
+	MOVED_PERMANENTLY = 301,
+	FOUND = 302,
+	SEE_OTHER = 303,
+	NOT_MODIFIED = 304,
+	USE_PROXY = 305,
+	TEMPORARY_REDIRECT = 307,
+
+	// 4xx client error
+	BAD_REQUEST = 400,
+	UNAUTHORIZED = 401,
+	PAYMENT_REQUIRED = 402,
+	FORBIDDEN = 403,
+	NOT_FOUND = 404,
+	METHOD_NOT_ALLOWED = 405,
+	NOT_ACCEPTABLE = 406,
+	PROXY_AUTHENTICATION_REQUIRED = 407,
+	REQUEST_TIMEOUT = 408,
+	CONFLICT = 409,
+	GONE = 410,
+	LENGTH_REQUIRED = 411,
+	PRECONDITION_FAILED = 412,
+	REQUEST_ENTITY_TOO_LARGE = 413,
+	REQUEST_URI_TOO_LONG = 414,
+	UNSUPPORTED_MEDIA_TYPE = 415,
+	REQUESTED_RANGE_NOT_SATISFIABLE = 416,
+	EXPECTATION_FAILED = 417,
+	UNPROCESSABLE_ENTITY = 422,
+	LOCKED = 423,
+	FAILED_DEPENDENCY = 424,
+	UPGRADE_REQUIRED = 426,
+
+	// 5xx server error
+	INTERNAL_SERVER_ERROR = 500,
+	NOT_IMPLEMENTED = 501,
+	BAD_GATEWAY = 502,
+	SERVICE_UNAVAILABLE = 503,
+	GATEWAY_TIMEOUT = 504,
+	HTTP_VERSION_NOT_SUPPORTED = 505,
+	INSUFFICIENT_STORAGE = 507,
+	NOT_EXTENDED = 510,
+};
+
+//-------------------------------------------------
+// Connection
+//
+// Handles the socket connection, issuing of requests and managing
+// responses.
+// ------------------------------------------------
+
+enum Connection_State { IDLE, REQ_STARTED, REQ_SENT };
+class Connection {
+	m_Port = null;
+	m_Host = null;
+	m_State = null;
+	m_Sock = null;
+	m_Buffer = null; // lines of request
+	m_Outstanding = null; // responses for outstanding requests
+	
+	
+	// doesn't connect immediately
+	constructor(host, port){
+		m_Host = host;
+		m_Port = port;
+		m_Buffer = [];
+		m_Outstanding = [];
+		m_State =Connection_State.IDLE;
+	}
+
+	// Don't need to call connect() explicitly as issuing a request will
+	// call it automatically if needed.
+	// But it could block (for name lookup etc), so you might prefer to
+	// call it in advance.
+	function connect(){
+		m_Sock = socket.tcp();
+		m_Sock.connect(m_Host, m_Port);
+		m_Sock.settimeout(0.01);
+	}
+
+	// close connection, discarding any pending requests.
+	function close(){
+		m_Sock.close();
+		m_Sock = null;
+	}
+
+	// Update the connection (non-blocking)
+	// Just keep calling this regularly to service outstanding requests.
+	function pump(milisec=10) { //10 miliseconds to prevent high cpu load
+		if( m_Outstanding.empty() ) return;		// no requests outstanding
+		assert( m_Sock != null );	// outstanding requests but no connection!
+
+		if( !datawaiting( m_Sock, milisec) ) return;	// recv will block
+
+		local rc = m_Sock.receive(2048);
+		switch(rc[1]){
+			case socket.IO_DONE:
+			case socket.IO_TIMEOUT:
+				break;
+			default:
+				throw(format("socket io error %d", rc[1]));
+		}
+		local buf = rc[0];
+		local a = buf.len();
+		if( a== 0 )
+		{
+			// connection has closed
+			local r = m_Outstanding[0];
+			r->notifyconnectionclosed();
+			assert( r->completed() );
+			m_Outstanding.remove(0);
+
+			// any outstanding requests will be discarded
+			close();
+		}
+		else
+		{
+			local used = 0;
+			while( used < a && !m_Outstanding.empty() )
+			{
+				local r = m_Outstanding[0];
+				local u = r->pump( buf, used, a-used );
+
+				// delete response once completed
+				if( r->completed() )	m_Outstanding.remove(0);
+				used += u;
+			}
+
+			// NOTE: will lose bytes if response queue goes empty
+			// (but server shouldn't be sending anything if we don't have
+			// anything outstanding anyway)
+			assert( used == a );	// all bytes should be used up by here.
+		}
+	}
+
+	// any requests still outstanding?
+	function outstanding() { return m_Outstanding && !m_Outstanding.empty(); }
+
+	// ---------------------------
+	// high-level request interface
+	// ---------------------------
+
+	// method is "GET", "POST" etc...
+	// url is only path part: eg  "/index.html"
+	// headers is array of name/value pairs, terminated by a null-ptr
+	// body & bodysize specify body data of request (eg values for a form)
+	function request( method, url, headers=null, body=null, bodysize=0){
+		local gotcontentlength = false;	// already in headers?
+
+		// check headers for content-length
+		// TODO: check for "Host" and "Accept-Encoding" too
+		// and avoid adding them ourselves in putrequest()
+		if( headers ) gotcontentlength = headers.get("content-length", false);
+
+		putrequest( method, url );
+
+		if( body && !gotcontentlength ) putheader( "Content-Length", bodysize );
+
+		if( headers ) foreach(name, value in headers) putheader( name, value );
+
+		endheaders();
+
+		if( body ) send( body, bodysize );
+	}
+
+	// ---------------------------
+	// low-level request interface
+	// ---------------------------
+
+	// begin request
+	// method is "GET", "POST" etc...
+	// url is only path part: eg  "/index.html"
+	function putrequest( method, url ){
+		if( m_State != Connection_State.IDLE ) throw ("Request already issued" );
+		if( !method || !url ) throw ( "Method and url can't be NULL" );
+
+		m_State = Connection_State.REQ_STARTED;
+
+		local req = format("%s %s HTTP/1.1", method, url);
+		m_Buffer.push( req );
+
+		putheader( "Host", m_Host );	// required for HTTP1.1
+
+		// don't want any fancy encodings please
+		putheader("Accept-Encoding", "identity");
+
+		// Push a new response onto the queue
+		local r = new Response( method, url, this );
+		m_Outstanding.push( r );
+	}
+
+	// Add a header to the request (call after putrequest() )
+	function putheader( header, value ){
+		if( m_State != Connection_State.REQ_STARTED ) throw ( "putheader() failed" );
+		m_Buffer.push( format("%s: %s", header, value.tostring()) );	
+	}
+
+	// Finished adding headers, issue the request.
+	function endheaders(){
+		if( m_State != Connection_State.REQ_STARTED ) throw "Cannot send header";
+		m_State = Connection_State.IDLE;
+		m_Buffer.push( "" );
+		m_Buffer.push( "" );
+		local msg = m_Buffer.concat("\r\n");
+		m_Buffer.clear();
+		send( msg , msg.len() );
+	}
+
+	// send body data if any.
+	// To be called after endheaders()
+	function send( buf, numbytes ){
+		if( !m_Sock ) connect();
+		local n = m_Sock.send( buf , 0, numbytes );
+		if(n != numbytes) throw("Could not send ");
+	}
+
+	// return true if socket has data waiting to be read
+	static function datawaiting( sock , milisec=0)
+	{
+		try {
+			local rc = socket.select( [sock], [], milisec ? milisec / 1000.0 : 0);
+			local rar = rc[0];
+			if(rar.len() == 1 && rar[0] == sock) return true;
+			return false;
+		}
+		catch(e){
+			if(e == "timeout") return false;
+			else throw(e);
+		}
+	}
+
+    function response_begin( r ) {}
+    function response_data( r, data, numbytes ) {}
+    function response_complete( r ) {}
+};
+
+enum Response_state {
+		STATUSLINE,		// start here. status line is first line of response.
+		HEADERS,		// reading in header lines
+		BODY,			// waiting for some body data (all or a chunk)
+		CHUNKLEN,		// expecting a chunk length indicator (in hex)
+		CHUNKEND,		// got the chunk, now expecting a trailing blank line
+		TRAILERS,		// reading trailers after body.
+		COMPLETE,		// response is complete!
+	};
+	
+class Response {
+	m_Connection = null; 	// to access callback ptrs
+	m_Method = null; 		// req method: "GET", "POST" etc...
+	m_Url = null; 			// req url: /image.php?d=2...
+	m_VersionString = null;	// HTTP-Version
+	m_Version = null;		// 10: HTTP/1.0    11: HTTP/1.x (where x>=1)
+	m_Status = null;		// Status-Code
+	m_Reason = null;		// Reason-Phrase
+	m_Headers = null;		// header/value pairs
+	m_BytesRead = null;		// body bytes read so far
+	m_Chunked = null;		// response is chunked?
+	m_ChunkLeft = null;		// bytes left in current chunk
+	m_Length = null;		// -1 if unknown
+	m_WillClose = null;		// connection will close at response end?
+	m_LineBuf = null;		// line accumulation for states that want it
+	m_HeaderAccum = null;	// accumulation buffer for headers
+	m_State = null;
+	
+	// only Connection creates Responses.
+	constructor(method, url, conn){
+		m_Method = method;
+		m_Url = url;
+		m_Connection = conn;
+		m_Version = 0;
+		m_Status = 0;
+		m_BytesRead = 0;
+		m_Chunked = false;
+		m_ChunkLeft = 0;
+		m_Length = -1;
+		m_WillClose = false;
+		m_Headers = {};
+		m_HeaderAccum = "";
+		m_LineBuf = "";
+		m_State = Response_state.STATUSLINE;
+	}
+	
+	// retrieve a header (returns null if not present)
+	function getheader( name ){
+		local lname = name.tolower();
+		return m_Headers.get(lname, null);
+	}
+	
+	function completed() { return m_State == Response_state.COMPLETE; }
+	
+	// get the HTTP status code
+	function getstatus(){
+		// only valid once we've got the statusline
+		assert( m_State != Response_state.STATUSLINE );
+		return m_Status;
+	}
+	
+	// get the HTTP response reason string
+	function getreason(){
+		// only valid once we've got the statusline
+		assert( m_State != Response_state.STATUSLINE );
+		return m_Reason;
+	}
+	
+	// true if connection is expected to close after this response.
+	function willclose() { return m_WillClose; }
+	
+	function getconnection(){return m_Connection;}
+	function geturl() { return m_Url; }
+	function getLength() { return m_Length;}
+	
+	// pump some data in for processing.
+	// Returns the number of bytes used.
+	// Will always return 0 when response is complete.
+	function pump( data, start, datasize ){
+		assert( datasize != 0 );
+		local count = datasize;
+		local data_idx = 0;
+
+		while( count > 0 && m_State != Response_state.COMPLETE )
+		{
+			if( m_State == Response_state.STATUSLINE ||
+				m_State == Response_state.HEADERS ||
+				m_State == Response_state.TRAILERS ||
+				m_State == Response_state.CHUNKLEN ||
+				m_State == Response_state.CHUNKEND )
+			{
+				// we want to accumulate a line
+				local pos = data.find("\n", data_idx);
+				if( pos >= 0 )
+				{
+					count -= pos-data_idx+1;
+					local new_pos = pos;
+					if(pos > 0 && data[pos-1] == '\r') --new_pos;
+					m_LineBuf = data.slice(data_idx, new_pos);
+					data_idx = pos+1;
+					// now got a whole line!
+					switch( m_State )
+					{
+						case Response_state.STATUSLINE:
+							ProcessStatusLine( m_LineBuf );
+							break;
+						case Response_state.HEADERS:
+							ProcessHeaderLine( m_LineBuf );
+							break;
+						case Response_state.TRAILERS:
+							ProcessTrailerLine( m_LineBuf );
+							break;
+						case Response_state.CHUNKLEN:
+							ProcessChunkLenLine( m_LineBuf );
+							break;
+						case Response_state.CHUNKEND:
+							// just soak up the crlf after body and go to next state
+							assert( m_Chunked == true );
+							m_State = Response_state.CHUNKLEN;
+							break;
+						default:
+							break;
+					}
+					m_LineBuf = "";
+				}
+			}
+			else if( m_State == Response_state.BODY )
+			{
+				local bytesused = 0;
+				if( m_Chunked )
+					bytesused = ProcessDataChunked( data, count );
+				else
+					bytesused = ProcessDataNonChunked( data, count );
+				data += bytesused;
+				count -= bytesused;
+			}
+		}
+		// return number of bytes used
+		return datasize - count;
+	}
+	
+	// tell response that connection has closed
+	function notifyconnectionclosed(){
+		if( m_State == Response_state.COMPLETE ) return;
+
+		// eof can be valid...
+		if( m_State == Response_state.BODY && 
+			!m_Chunked && m_Length <= 0 ) Finish();	// we're all done!
+		else throw ( "Connection closed unexpectedly" );
+	}
+	
+	function FlushHeader(){
+		if( m_HeaderAccum.empty() ) return;	// no flushing required
+		local rc = m_HeaderAccum.match("([^:]+):%s*(.+)");
+		if(!rc) throw(format("Invalid header (%s)", m_HeaderAccum));
+		m_Headers[ rc[0].tolower() ] <- rc[1];
+		m_HeaderAccum = "";
+	}
+
+	function ProcessStatusLine( line ){
+		//HTTP/1.1 200 OK
+		local rc = line.match("%s*(%S+)%s+(%d+)%s+(.+)");
+		if(!rc) throw(format("BadStatusLine (%s)", line));
+		m_VersionString = rc[0];
+		m_Status = rc[1].tointeger();
+		m_Reason = rc[2];
+
+		if( m_Status < 100 || m_Status > 999 ) throw ( format("BadStatusLine (%s)", line) );
+
+		if( m_VersionString == "HTTP:/1.0" ) m_Version = 10;
+		else if( m_VersionString.startswith( "HTTP/1." ) ) m_Version = 11;
+		else throw ( format("UnknownProtocol (%s)", m_VersionString) );
+		// TODO: support for HTTP/0.9
+
+		// OK, now we expect headers!
+		m_State = Response_state.HEADERS;
+		m_HeaderAccum = "";		
+	}
+	
+	function ProcessHeaderLine( line ){
+		if( line.empty() )
+		{
+			FlushHeader();
+			// end of headers
+
+			// HTTP code 100 handling (we ignore 'em)
+			if( m_Status == HTTP_status_code.CONTINUE )
+				m_State = Response_state.STATUSLINE;	// reset parsing, expect new status line
+			else
+				BeginBody();			// start on body now!
+			return;
+		}
+
+		if( line[0] == ' ' )
+		{
+			// it's a continuation line - just add it to previous data
+			m_HeaderAccum += line;
+		}
+		else
+		{
+			// begin a new header
+			FlushHeader();
+			m_HeaderAccum = line;
+		}
+	}
+	
+	function ProcessTrailerLine(line){
+		// TODO: handle trailers?
+		// (python httplib doesn't seem to!)
+		if( line.empty() ) Finish();
+		// just ignore all the trailers...
+	}
+	
+	function ProcessChunkLenLine( line ){
+		// chunklen in hex at beginning of line
+		m_ChunkLeft = line.tointeger(16);
+
+		if( m_ChunkLeft == 0 )
+		{
+			// got the whole body, now check for trailing headers
+			m_State = Response_state.TRAILERS;
+			m_HeaderAccum = "";
+		}
+		else
+		{
+			m_State = Response_state.BODY;
+		}
+	}
+	
+	function ProcessDataChunked( data, count ){
+		assert( m_Chunked );
+
+		local n = count;
+		if( n>m_ChunkLeft ) n = m_ChunkLeft;
+
+		// invoke callback to pass out the data
+		m_Connection.response_data( this, data, n );
+
+		m_BytesRead += n;
+
+		m_ChunkLeft -= n;
+		assert( m_ChunkLeft >= 0);
+		if( m_ChunkLeft == 0 )
+		{
+			// chunk completed! now soak up the trailing CRLF before next chunk
+			m_State = Response_state.CHUNKEND;
+		}
+		return n;
+	}
+	
+	function ProcessDataNonChunked( data, count ){
+		local n = count;
+		if( m_Length != -1 )
+		{
+			// we know how many bytes to expect
+			local remaining = m_Length - m_BytesRead;
+			if( n > remaining ) n = remaining;
+		}
+
+		// invoke callback to pass out the data
+		m_Connection.response_data( this, data, n );
+		m_BytesRead += n;
+
+		// Finish if we know we're done. Else we're waiting for connection close.
+		if( m_Length != -1 && m_BytesRead == m_Length ) Finish();
+		return n;
+	}
+	
+	// OK, we've now got all the headers read in, so we're ready to start
+	// on the body. But we need to see what info we can glean from the headers
+	// first...
+	function BeginBody(){
+		m_Chunked = false;
+		m_Length = -1;	// unknown
+		m_WillClose = false;
+
+		// using chunked encoding?
+		local trenc = getheader( "transfer-encoding" );
+		if( trenc && trenc == "chunked" )
+		{
+			m_Chunked = true;
+			m_ChunkLeft = -1;	// unknown
+		}
+
+		m_WillClose = CheckClose();
+
+		// length supplied?
+		local contentlen = getheader( "content-length" );
+		if( contentlen && !m_Chunked )
+		{
+			m_Length = contentlen.tointeger();
+		}
+
+		// check for various cases where we expect zero-length body
+		if( m_Status == HTTP_status_code.NO_CONTENT ||
+			m_Status == HTTP_status_code.NOT_MODIFIED ||
+			( m_Status >= 100 && m_Status < 200 ) ||		// 1xx codes have no body
+			m_Method == "HEAD" )
+		{
+			m_Length = 0;
+		}
+
+
+		// if we're not using chunked mode, and no length has been specified,
+		// assume connection will close at end.
+		if( !m_WillClose && !m_Chunked && m_Length == -1 ) m_WillClose = true;
+
+		// Invoke the user callback, if any
+		m_Connection.response_begin( this );
+
+	/*
+		printf("---------BeginBody()--------\n");
+		printf("Length: %d\n", m_Length );
+		printf("WillClose: %d\n", (int)m_WillClose );
+		printf("Chunked: %d\n", (int)m_Chunked );
+		printf("ChunkLeft: %d\n", (int)m_ChunkLeft );
+		printf("----------------------------\n");
+	*/
+		// now start reading body data!
+		if( m_Chunked ) m_State = Response_state.CHUNKLEN;
+		else m_State = Response_state.BODY;
+	}
+	
+	function CheckClose(){
+		if( m_Version == 11 )
+		{
+			// HTTP1.1
+			// the connection stays open unless "connection: close" is specified.
+			local conn = getheader( "connection" );
+			if( conn && conn == "close" ) return true;
+			else return false;
+		}
+
+		// Older HTTP
+		// keep-alive header indicates persistant connection
+		if( getheader( "keep-alive" ) ) return false;
+
+		// TODO: some special case handling for Akamai and netscape maybe?
+		// (see _check_close() in python httplib.py for details)
+		return true;
+	}
+	
+	function Finish(){
+		m_State = Response_state.COMPLETE;
+		
+		// invoke the callback
+		m_Connection.response_complete( this );
+	}
+}
+
+class MyConnection extends Connection {
+	count = null;
+	
+	constructor(host, port){
+		base.constructor(host, port);
+		count = 0;
+	}
+	function response_begin( r ) {
+		printf( "BEGIN (%d %s)\n", r->getstatus(), r->getreason() );
+		count = 0;
+	}
+	function response_data( r, data, numbytes ) {
+		print( data );
+		count += numbytes;
+	}
+	function response_complete( r ) {
+		printf( "COMPLETE (%d bytes)\n", count );
+	}
+}
+
+local conn = MyConnection( "www.scumways.com", 80);
+
+conn.request( "GET", "/happyhttp/test.php" );
+
+while( conn.outstanding() ) conn.pump();

+ 45 - 0
ourbiz/ourbiz-fltk.nut

@@ -0,0 +1,45 @@
+function _tr(str){ return str;}
+
+class MyBaseWindow extends Fl_Window {
+	childWindows=null;
+
+	constructor(px, py, pw, ph, pl) {
+		base.constructor(px, py, pw, ph, pl);
+		childWindows = {};
+	}
+
+	function showChildWindow(winName, WindowClass){
+		local win = childWindows.get(winName, false);
+		if(!win){
+			win = new WindowClass();
+			win.label(winName);
+			childWindows[winName] <- win;
+		}
+		win->show();
+		return win;
+	}
+}
+
+class Fl_Data_Table extends Flv_Table {
+	constructor(px, py, pw, ph, pl=""){
+		base.constructor(px, py, pw, ph, pl);
+	}
+}
+
+dofile("utils-fltk.nut");
+dofile("base-report-A4.nut");
+dofile("invoice-A4.nut");
+dofile("edit-product-window.nut");
+dofile("edit-entity-window.nut");
+dofile("edit-order-window.nut");
+dofile("list-search-window.nut");
+dofile("sales-tax-window.nut");
+dofile("main-window.nut");
+
+
+local win = new MainWindow(10, 50, 330, 320, "OURBIZ");
+//local win = new SalesTaxRatesEditWindow();
+win->resizable(win);
+win->show_main();
+
+Fl.run();

+ 1702 - 0
ourbiz/ourbiz.nut

@@ -0,0 +1,1702 @@
+local globals = getroottable();
+if(!globals.get("APP_CODE_FOLDER", false)) ::APP_CODE_FOLDER <- ".";
+
+local constants = getconsttable();
+
+function getOurbizDBFileName(){
+	if (globals.get("jniLog", false)) return APP_CODE_FOLDER + "/ourbiz.db";
+	return "/home/mingo/dev/FrontAccountLua/ourbiz.db";
+}
+
+::ourbizDB <- null;
+function getOurbizDB(){
+	if(!::ourbizDB) ::ourbizDB = SQLite3(getOurbizDBFileName());
+	return ::ourbizDB;
+	//return checkCachedDB(APP_CODE_FOLDER + "/ourbiz.db");
+}
+
+dofile(APP_CODE_FOLDER + "/pdf-table.nut");
+
+function escape_sql_like_search_str(str){
+    if (str && (str.len() > 0)){
+        str = str.gsub("%%", "%%%%");
+        if (str.find(" ") == 0)
+            str = str.gsub("^%s*(.+)%s*$","%1%%");
+        else
+            str = str.gsub("^%s*(.+)%s*$","%%%1%%");
+    }
+    //print("escape_sql_like_search_str +" + str + "+")
+    return str;
+}
+
+function mkEmptyWhenZero(tbl, key){
+	if (type(key) == "table"){
+		foreach( k,v in key ) {
+			if (tbl[v] == "0") tbl[v] = "";
+		}
+	}
+	else if (tbl[key] == 0) tbl[key] = "";
+}
+
+constants.rawdelete("TimePeriode");
+enum TimePeriode {is_years = 1, is_months, is_weeks, is_days};
+
+function getStatisticsPeriodeType(speriode){
+	if(speriode == "years") return TimePeriode.is_years;
+	else if(speriode == "weeks") return TimePeriode.is_weeks;
+	else if(speriode == "days") return TimePeriode.is_days;
+	return TimePeriode.is_months;
+}
+
+function get_sql_bar_chart_statistics_periodes (periode_count, periode_type){
+	local speriode2;
+	local periodeMultiplier = 1;
+	local speriode;
+
+	switch(periode_type){
+		case TimePeriode.is_years:{
+			speriode2 = "%Y";
+			speriode = "years";
+		}
+		break;
+		case TimePeriode.is_weeks:{
+			periodeMultiplier = 7;
+			speriode2 = "%Y-%W";
+			speriode = "days";
+		}
+		break;
+		case TimePeriode.is_days:{
+			speriode2 = "%Y-%m-%d";
+			speriode = "days";
+		}
+		break;
+		default:{
+			speriode2 = "%Y-%m";
+			speriode = "months";
+		}
+	}
+
+	periode_count = periode_count * periodeMultiplier;
+	local result_periode = format("strftime('%s', order_date)", speriode2);
+	local result_periode_count = format("date('now', '-%d %s')", periode_count, speriode);
+	return [result_periode, result_periode_count];
+}
+
+function getOptionsFromMap(map){
+	local opt = {};
+        opt.search_str <- map.get("search_str", null);
+        opt.select_fields <- map.get("select_fields", null);
+        opt.search_on <- map.get("search_on", "1"); //to make easy on html interface
+	local CHECK_BOOL = function(field){
+		local value = map.get(field, null);
+		if (value == "1") opt[field] <- "1";
+		else opt[field] <- null;
+	}
+	local math_floor = math.floor;
+	local CHECK_INT_DFLT = function(field, dflt) {
+		local value = map.get(field, dflt).tointeger();
+		opt[field] <- math_floor(value);
+	}
+	local CHECK_INT = function(field) {CHECK_INT_DFLT(field, 0) };
+
+        CHECK_BOOL("active");
+        CHECK_BOOL("buys");
+        CHECK_BOOL("cdate");
+        CHECK_BOOL("group_set");
+        CHECK_BOOL("inactive");
+        CHECK_BOOL("mdate");
+        CHECK_BOOL("only_prices_older");
+        CHECK_BOOL("order_by_creation");
+        CHECK_BOOL("order_by_modification");
+        CHECK_BOOL("sales");
+        CHECK_INT("entity_id");
+        CHECK_INT("group_id");
+        CHECK_INT("image_id");
+        CHECK_INT("account_id");
+        CHECK_INT("order_id");
+        CHECK_INT("payment_type_id");
+        CHECK_INT("product_id");
+        CHECK_INT_DFLT("query_limit", 50);
+        CHECK_BOOL("contact");
+        CHECK_BOOL("date");
+        CHECK_BOOL("description");
+        CHECK_BOOL("entities");
+        CHECK_BOOL("id");
+        CHECK_BOOL("name");
+        CHECK_BOOL("notes");
+        CHECK_BOOL("phone");
+        CHECK_BOOL("products");
+        CHECK_BOOL("reference");
+        CHECK_BOOL("total");
+        CHECK_BOOL("with_images");
+        CHECK_BOOL("with_headers");
+        CHECK_BOOL("with_accounts");
+        CHECK_BOOL("code");
+	return opt;
+}
+
+function checkQueryStringSAB(qs_tbl, so){
+	local qs_sab = qs_tbl.get("sab", null);
+	if (qs_sab){
+		if (qs_sab == "S") so.sales <- true;
+		else if (qs_sab == "B") so.buys <- true;
+	}
+}
+
+function get_search_options(req){
+	local search_opt = getOptionsFromMap(req);
+
+	local sab = req.get("sab", null);
+	if (sab && sab.len() > 0){
+		local c = sab.toupper();
+		if (c == "S") search_opt.sales <- true;
+		else if (c == "B") search_opt.buys <- true;
+	}
+	return search_opt;
+}
+
+
+class DB_Manager {
+	table_name = null;
+	editable_fields = null;
+	has_mdate = null;
+	has_version = null;
+	
+	constructor(ptable_name, peditable_fields = ["is_active", "code", "description"]){
+		table_name = ptable_name;
+		editable_fields = peditable_fields;
+		has_mdate = true;
+		has_version = true;
+	}
+	
+	function db_action(db, data){
+		local action = data.__action__;
+		if (action == "insert") return db_insert(db,data);
+		else if (action == "update") return db_update(db,data);
+		else if (action == "delete") return db_delete(db,data);
+	}
+
+	function db_insert(db, data){
+		local mf = blob();
+		mf.write("insert into ", table_name,  "(")
+		local isFirst = true;
+		foreach( k,v in editable_fields) {
+			if (data.get(v, false)){
+				if (isFirst) isFirst = false;
+				else mf.write(",");
+				mf.write(v);
+			}
+		}
+		mf.write(") values(");
+		isFirst = true;
+		foreach( k,v in editable_fields) {
+			if (data.get(v, false)){
+				if (isFirst) isFirst = false;
+				else mf.write(",");
+				mf.write("?");
+			}
+		}
+		mf.write(")");
+		
+		local stmt = db.prepare(mf.tostring());
+		local x = 0;
+		foreach( k,v in editable_fields) {
+			if (data.get(v, false)){
+				stmt.bind_empty_null(++x, data[v]);
+			}
+		}			
+		local result = stmt.step();
+		stmt.finalize()
+		if (result == sqlite3.DONE) return db.last_insert_rowid();
+		throw db.error_message();
+	}
+
+	function db_update(db, data){
+		local mf = blob();
+		mf.write("update ", table_name,  " set ");
+		local isFirst = true;
+		foreach( k,v in editable_fields) {
+			if (data.get(v, false)){
+				if (isFirst) isFirst = false;
+				else mf.write(",");
+				mf.write(v, "=?");
+			}
+		}
+		if (has_mdate) mf.write(", mdate=CURRENT_TIMESTAMP ");
+		if (has_version) mf.write(", _version_=_version_+1 ");
+
+		mf.write(" where id=? ");
+		if (self.has_version) mf.write(" and _version_=?");
+		
+		local stmt = db.prepare(mf.tostring());
+		local x = 0;
+		foreach( k,v in editable_fields) {
+			if (data.get(v, false)) {
+				stmt.bind_empty_null(++x, data[v]);
+			}
+		}			
+		stmt.bind(++x, data.__id__);
+		if (has_version) stmt.bind(++x, data.__version__);
+		
+		local result = stmt.step();
+		stmt.finalize();
+		if (result == sqlite3.SQLITE_DONE) return db.changes();
+		throw db.error_message();
+	}
+
+	function db_delete(db, data){
+		local mf = blob();
+		mf.write("delete from ", table_name, " where id=? ");
+		if (has_version) mf.write(" and _version_=?");
+		
+		local stmt = db.prepare(mf.tostring());
+		stmt.bind(1, data.__id__);
+		if (has_version) stmt.bind(2, data.__version__);
+
+		local result = stmt.step();
+		stmt.finalize();
+		if (result == sqlite3.DONE) return db.changes();
+		throw db.error_message();
+	}
+	
+	function sql_get_one(req) {
+		return format("select * from %s where id=?", table_name); 
+	}
+	
+	function sql_list(qs_tbl=null, post_tbl=null) {
+		return format("select id, code, description, is_active from %s order by description", table_name); 
+	}
+	
+	function sql_short_list(req) {
+		return format("select id, description from %s where is_active=1 order by 2", table_name); 
+	}
+
+	function get_bar_chart_statistics_sql_core(aId, sab, str1, str2){
+		local mf = blob();
+
+		mf.write("SELECT ", str1, " as qm, sum(subtotal - total_discount + total_sales_tax1 + total_sales_tax2) as q, '", 
+			sab, [==[' as sab
+FROM orders as o
+WHERE entity_id = ]==], aId);
+		if (sab == "S" || sab == "B"){
+			mf.write(" and o.order_type_id in(select * from order_types_");
+			if (sab == "S") mf.write("sell");
+			else mf.write("buy");
+			mf.write("_payment) ");
+		}
+		mf.write(" and o.order_date >= ", str2, " group by qm ");
+		//debug_print(tostring(mf), "\n");
+		return mf.tostring();
+	}
+}
+
+local db_ourbiz_tables = {};
+
+//
+// entities
+//
+
+class DB_Entities extends DB_Manager {
+	constructor(){
+		base.constructor("entities", [
+		"address", "city", "company", "contact",
+		"country", "email", "fax", "gps_coordinates", "group_id",
+		"image_id", "is_active", "name", "notes", "parent_id", "phone",
+		"sales_tax_exempt", "show_on_buys", "show_on_sales", "state",
+		"tags", "tax_number", "use_sales_tax2", "user_code", "web", "zip",
+		"irpf_pct_retention"]);
+	}
+	
+	function past_products_sql(entity_id){
+		return format([==[
+SELECT
+    product_id as 'id|ID|6|R',
+    sell_description as 'sell_description|Product|-1',
+    sum(quantity) as 'quantity|Quantity|8|R',
+    sum(quantity*price) as 'amount|Amount|8|R|M',
+    code as 'order_type_code|Type|4|C'
+    FROM orders_lines as ol, orders as o, order_types as ot, products as p
+    WHERE o.entity_id = %d
+    and ot.id = o.order_type_id
+    and ol.order_id = o.id
+    and p.id = ol.product_id
+    GROUP BY product_id, code
+    ORDER BY 3 desc
+]==], entity_id);
+	}
+
+	static function sales_history_sql(history_type, query_limit, entity_id){
+		// Select history type
+		history_type = history_type.tointeger();
+		if (history_type < 1) {return "select '' as 'Select one|-1';" };
+
+		entity_id = entity_id.tointeger();
+		local mf = blob();
+		if (history_type < 3){
+			mf.write([==[
+SELECT o.id as 'id|ID|6|R', o.order_date as 'order_date|Date|10',
+	ot.code as 'order_type_code|Type|7|C', pt.code as 'payment_type_code|P.T.|4|C',
+	discount_amt as 'discount_amt|Disc.|9|R|ZM', total as 'total|Total|9|R|M'
+FROM orders as o
+LEFT JOIN order_types as ot
+	ON o.order_type_id = ot.id
+LEFT JOIN payment_types as pt
+	ON o.payment_type_id = pt.id
+    , (
+    SELECT order_id, sum(discount_amt) as  discount_amt, sum(total) as total
+    FROM order_line_calc_view
+    WHERE order_id in(SELECT id FROM orders WHERE entity_id =]==], entity_id, [==[)
+    GROUP BY order_id
+    )  as ott
+    WHERE entity_id =]==], entity_id, " and o.id = ott.order_id");
+		}
+		else
+		{
+			local strTmp = format(" products_by_entity_view where entity_id =%d ", entity_id);
+			local strTmp2 = " (price * quantity) ";
+			local strTmp3 = " code ";
+
+			mf.write([==[
+select product_id as 'product_id|ID|8|R', description as "description|Product|-1",
+	sum(quantity) as 'quantity|Qty.|9|R|N', sum(]==], strTmp2, [==[) as "amount|Amount|9|R|M",
+]==], strTmp3, [==[ as "order_type_code|Type|6|C" 
+from ]==], strTmp, [==[
+group by product_id, description, ]==], strTmp3);
+		}
+
+		switch(history_type){
+			case 1: mf.write(" order by order_date desc, o.id desc "); break;
+			case 2: mf.write(" order by total desc "); break;
+			case 3: mf.write(" order by description "); break;
+			case 4: mf.write(" order by 4 desc "); break;
+			case 5: mf.write(" order by 3 desc "); break;
+		}
+	
+		mf.write(" limit ", query_limit.tointeger());
+		//debug_print(tostring(mf), "\n");
+		return mf.tostring();
+	}
+
+	function sql_bar_chart_statistics(aId, sab, periode_count, periode_type){
+		local mf = blob();
+		local rc = get_sql_bar_chart_statistics_periodes(periode_count, periode_type);
+		local speriode = rc[0], speriode_count = rc[1];
+
+		if (sab == "S" || sab == "B"){
+			mf.write(get_bar_chart_statistics_sql_core(aId, sab, speriode, speriode_count));
+		}
+		else
+		{
+			mf.write("select qm, q, sab from (")
+			mf.write(get_bar_chart_statistics_sql_core(aId, "S", speriode, speriode_count))
+			mf.write(" UNION ALL ")
+			mf.write(get_bar_chart_statistics_sql_core(aId, "B", speriode, speriode_count))
+			mf.write(") as t ")
+		}
+
+	    mf.write(" order by qm, sab")
+	    //debug_print(tostring(mf), "\n")
+	    return mf.tostring();
+	}
+
+	function sql_search_list(qs_tbl, post_tbl){
+		local so = get_search_options(post_tbl);
+		checkQueryStringSAB(qs_tbl, so);
+		local mf = blob();
+		
+		mf.write(" select e.id, e.name, e.contact, e.phone, e.is_active, e.image_id ");
+		if (so.with_images) mf.write(", i.thumbnail, i.mime_type ");
+		mf.write(" from entities as e ");
+		if (so.with_images) mf.write(" left join images as i on e.image_id = i.id ");
+		mf.write(" where ");
+
+		if  ((!so.group_id) &&  (!so.product_id) && (! (so.search_str && (so.search_str.len() > 0)))){
+			//special case where we get the latest entities that made any transaction
+			mf.write(" e.id in(select distinct entity_id from orders as o ");
+			if (so.sales || so.buys){
+				mf.write(", order_types as ot where o.order_type_id = ot.id and ot.group_order =");
+			}
+			if (so.sales) mf.write("'S'");
+			else if (so.buys) mf.write("'B'");
+		
+			mf.write(" order by o.id desc");
+			if (so.query_limit != 0) mf.write(" limit ", so.query_limit);
+			mf.write(") order by 2");
+			//print(out_sql);
+			return mf.tostring();
+		}
+
+		if (so.mdate ) mf.write(" e.mdate is not null order by mdate desc ");
+		else if (so.cdate) mf.write(" 1=1 order by e.id desc ");
+
+		if (so.sales && so.buys) mf.write(" 1=1 ");
+		else if (so.sales || so.buys){
+			if (so.sales) mf.write(" show_on_sales = 1 ");
+			else if (so.buys) mf.write(" show_on_buys = 1 ");
+		}
+		else mf.write(" 1=1 ");
+
+		if (so.group_id && so.group_id != 0){
+			//mf.write(" and id in( select entity_id from entity_groups_link where group_id="
+			mf.write(" and e.group_id=", so.group_id);
+		}
+
+		if (so.active) mf.write(" and e.is_active=1 ");
+
+		local search_str = escape_sql_like_search_str(so.search_str);
+		if (so.product_id && so.product_id != 0){
+			mf.write(" and e.id in(select entity_id from orders_lines as ol, orders as o2 ");
+
+			if (so.sales || so.buys){
+				mf.write(" join order_types as ot2 on o2.order_type_id = ot2.id and ot2.group_order = ");
+				if (so.sales) mf.write(" 'S' ");
+				else if (so.buys) mf.write(" 'B' ");
+			}
+
+			mf.write("where ol.product_id = ",  so.product_id, " and ol.order_id = o2.id order by ol.id desc ");
+			if (so.query_limit != 0) mf.write(" limit ", so.query_limit);
+			mf.write(")");
+		}
+		else if (search_str && search_str.len() > 0){
+			if (so.id && so.id != 0) mf.write(" and e.id = ", so.search_str.tointeger());
+			else
+			{
+				if (so.products){
+					mf.write(" and e.id in ( select entity_id from orders where id in (",
+						" select order_id from orders_lines where ",
+						" description like "", search_str, "" order by id desc )) ");
+				}
+				else
+				{
+					mf.write(" and ");
+					if (so.contact) mf.write(" e.contact ");
+					else if (so.notes) mf.write(" e.notes ");
+					else if (so.phone) mf.write(" e.phone ");
+					else mf.write(" e.name ");
+					mf.write(" like '", search_str, "' ");
+				}
+			}
+		}
+
+		mf.write(" order by e.name ");
+
+		if (so.query_limit && so.query_limit != 0) mf.write(" limit ", so.query_limit);
+		//debug_print(tostring(mf), "\n")
+		return  mf.tostring();
+	}
+
+	function sql_list(qs_tbl, post_tbl){
+		if (qs_tbl.get("search", false)) return sql_search_list(qs_tbl, post_tbl);
+		else if (qs_tbl.get("past_products", false)) return past_products_sql(qs_tbl.past_products);
+		else if (qs_tbl.get("history", false)){
+			local htype = qs_tbl.get("htype", 0);
+			local query_limit = qs_tbl.get("query_limit", 50).tointeger();
+			return sales_history_sql(htype, query_limit, qs_tbl.history);
+		}
+		else if (qs_tbl.get("statistics", false)){
+			local periode_count = qs_tbl.get("periode_count", 12).tointeger();
+			local periode_type = getStatisticsPeriodeType(qs_tbl.get("periode_type", "months"));
+			local sab = qs_tbl.get("sab", "S");
+			return sql_bar_chart_statistics(qs_tbl.get("statistics", 0).tointeger(), sab, periode_type, periode_count);
+		}
+		else if (qs_tbl.get("print_list", false)){
+			return [==[
+select id as 'id|ID|6|R', name as 'name|Name|-1', contact as 'contact|Contact|12', phone as 'phone|Phone|12'
+from entities order by name
+]==];
+		}
+		else if (qs_tbl.get("pdf", false)){
+			local clipped = qs_tbl.get("clipped", false);
+			local pdf = new PdfSqlTable();
+			pdf.page_title = "Entities List";
+			pdf.water_mark = "T H I S   I S   A   D E M O";
+
+			local sql = [==[
+select id as 'id|ID|6|R', name as 'name|Name|-1',
+	contact as 'contact|Contact|12',
+	phone as 'phone|Phone|12' 
+from entities 
+order by name
+]==]
+			local db = getOurbizDB();
+			local mf = blob();
+			pdf.GetPDF(db, sql, clipped, mf);
+			qs_tbl._doc_pdf_ <- mf;
+			return true;
+		}
+	}
+}
+
+db_ourbiz_tables.entities <- new DB_Entities();
+
+
+//
+// orders
+//
+
+dofile(APP_CODE_FOLDER +"/pdf-order.nut");
+
+class My_PDF_Order extends PDF_Order {
+	_tr_map = null;
+	_lang = null;
+	_tr_stmt = null;
+	my_logo_image = null;
+
+	constructor(db, lang){
+		base.constructor();
+		_lang = lang;
+		_tr_map = {};
+		my_logo_image = false;
+		_tr_stmt = db.prepare(" select svalue from translations_values as tv, translations_keys as tk, languages as l "
+			" where l.lang=? and tk.skey=? and tv.lang_id=l.id and tv.key_id=tk.id ");
+	}
+
+	function do_init(){
+		local map = {};
+		base.do_init();
+		/*
+		map[CFG_ORDER_COMPANY_NAME] <- "OurBiz";
+		map[CFG_ORDER_COMPANY_INFO] <- "Our buziness on our pocket.";
+		map[CFG_ORDER_BOTTOM_INFO] <- "Thanks for choose our products and services.";
+		configGetValues(*_tr_stmt.get_db(), map);
+		page_title = map[CFG_ORDER_COMPANY_NAME];
+		page_title2 = map[CFG_ORDER_COMPANY_INFO];
+		page_footer = map[CFG_ORDER_BOTTOM_INFO];
+		*/
+		page_title = "OurBiz";
+		page_title2 =  "Our buziness on our pocket.";
+		page_footer = "Thanks for choose our products and services.";
+	}
+
+	function _tr(str)
+	{
+/*
+		local tr_str = _tr_map.get(str, null);
+		if(tr_str) return tr_str;
+
+		_tr_stmt.reset();
+		_tr_stmt.bind(1, _lang);
+		_tr_stmt.bind(2, str);
+		if(_tr_stmt.next_row()) tr_str = _tr_stmt.col(0);
+		_tr_map[str] = tr_str || str;
+*/
+		return str;
+	}
+
+	function LogoImage(px, py, pwidth){
+		local db = _tr_stmt.get_db();
+		local stmt = db.prepare("select image, mime_type from images where name = 'order_logo'");
+		if(stmt.next_row())
+		{
+			my_logo_image = stmt.col(0);
+			local mime_type = stmt.col(1);
+			local mtype = "unknown";
+			if(mime_type == "image/jpeg") mtype = "jpg";
+			else if(mime_type == "image/png") mtype = "png";
+			Image("order_logo", my_logo_image, my_logo_image.size(), px, py, pwidth, 0, mtype);
+		}
+        }
+}
+
+class CalcOrderLine
+{
+	id = null;
+	order_id = null;
+	price_decimals = null;
+	product_id = null;
+	quantity = null;
+	weight = null;
+	unit_weight = null;
+	price = null;
+	first_total = null;
+	discount_pct = null;
+	discount_amt = null;
+	line_subtotal = null;
+	sales_tax1_pct = null;
+	sales_tax1_amt = null;
+	sales_tax2_pct = null;
+	sales_tax2_amt = null;
+	line_total = null;
+	use_sales_tax2 = null;
+	tax_exempt = null;
+
+	constructor(){
+		reset();
+	}
+
+	//reset is not the same as clear
+	//reset puts instance variables as when created
+	//and clear preserves tax flags
+	function reset(){
+		use_sales_tax2 = tax_exempt = false;
+		clear_preserving_tax_flags();
+	}
+
+	function calc_map(map){
+		local fields = [
+			"unit_weight", "quantity", "weight", "price",
+			"first_total", "discount_pct", "discount_amt",
+			"line_subtotal", "sales_tax1_pct", "sales_tax1_amt",
+			"sales_tax2_pct", "sales_tax2_amt", "line_total"
+			];
+		use_sales_tax2 = map.get("use_sales_tax2", false) == "1";
+		tax_exempt = map.get("tax_exempt", false) == "1";
+		price_decimals = map.get("price_decimals", 2).tointeger();
+		
+		foreach(field in fields){
+			this[field] = map.get(field, 0.0).tofloat();
+		}
+
+		calc();
+		
+		foreach(field in fields){
+			map[field] <- this[field];
+		}
+	}
+
+	function clear_preserving_tax_flags(withFullTax=false)
+	{
+		unit_weight = quantity = weight = price =
+                                              first_total = discount_pct =
+                                                      discount_amt = line_subtotal =
+                                                              sales_tax1_pct = sales_tax1_amt = sales_tax2_pct =
+                                                                      sales_tax2_amt = line_total = 0.0;
+		id = order_id = product_id = 0;
+		price_decimals = 2;
+		if(withFullTax){
+			use_sales_tax2 = true;
+			tax_exempt=false;
+		}
+	}
+
+	function dumpSLSArrayCalcNames(out_result)
+	{
+		//this list must match the dumpSLSArrayCalc order
+		add2sle(out_result, "first_total");
+		add2sle(out_result, "discount_amt");
+		add2sle(out_result, "line_subtotal");
+		add2sle(out_result, "sales_tax1_amt");
+		add2sle(out_result, "sales_tax2_amt");
+		add2sle(out_result, "line_total");
+	}
+
+	function dumpSLSArrayCalc(out_result)
+	{
+		//this must match the dumpSLSArrayCalcNames order
+		add2sle(out_result, first_total);
+		add2sle(out_result, discount_amt);
+		add2sle(out_result, line_subtotal);
+		add2sle(out_result, sales_tax1_amt);
+		add2sle(out_result, sales_tax2_amt);
+		add2sle(out_result, line_total);
+	}
+
+	function calc()
+	{
+		local num100 = 100;
+		first_total = quantity * price;
+		weight = unit_weight * quantity;
+		local round = math.broundf;
+
+		discount_amt = first_total * (discount_pct/num100);
+		line_subtotal = round(first_total - discount_amt, price_decimals);
+
+		if(!tax_exempt)
+		{
+			sales_tax1_amt = round(line_subtotal * (sales_tax1_pct/num100), price_decimals);
+			if(use_sales_tax2)
+			{
+				sales_tax2_amt = round(line_subtotal * (sales_tax2_pct/num100), price_decimals);
+			}
+			else
+			{
+				sales_tax2_pct = 0.0;
+			}
+		}
+		else
+		{
+			sales_tax2_pct = sales_tax1_pct = 0.0;
+		}
+		line_total = round(line_subtotal + sales_tax1_amt + sales_tax2_amt, price_decimals);
+	}
+}
+
+class  CalcOrderTotals
+{
+	_stmt_calc_order = null;
+	_stmt_get_tax_usage = null;
+
+	subtotal_amt = null;
+	discount_amt = null;
+	sales_tax1_amt = null;
+	sales_tax2_amt = null;
+	total_amt = null;
+	weight_total = null;
+	lines_count = null;
+    
+	constructor()
+	{
+		clear();
+		_stmt_calc_order = _stmt_get_tax_usage = false;
+	}
+	function clear()
+	{
+		subtotal_amt = discount_amt = sales_tax1_amt =
+                                          sales_tax2_amt = total_amt = weight_total = 0.0;
+		lines_count = 0;
+	}
+
+	function dumpSLEFieldNames(out_result)
+	{
+		add2sle(out_result, "lines_count");
+		add2sle(out_result, "weight_total");
+		add2sle(out_result, "subtotal_amt");
+		add2sle(out_result, "discount_amt");
+		add2sle(out_result, "sales_tax1_amt");
+		add2sle(out_result, "sales_tax2_amt");
+		add2sle(out_result, "total_amt");
+	}
+	
+	function dumpSLEFieldValues(out_result)
+	{
+		add2sle(out_result, lines_count);
+		add2sle(out_result, weight_total);
+		add2sle(out_result, subtotal_amt);
+		add2sle(out_result, discount_amt);
+		add2sle(out_result, sales_tax1_amt);
+		add2sle(out_result, sales_tax2_amt);
+		add2sle(out_result, total_amt);
+	}
+    
+	function dumpSLEArray(out_result)
+	{
+		out_result.write("[[");
+		dumpSLEFieldNames(out_result);
+		out_result.write(SLEEND);
+		out_result.write("][");
+		dumpSLEFieldValues(out_result);
+		out_result.write(SLEEND);
+		out_result.write("]");
+	}
+
+	function create_stmt_calc_order(db){
+		if(!_stmt_get_tax_usage)
+		{
+			_stmt_get_tax_usage = db.prepare([==[
+select entity_sales_tax_exempt, entity_use_sales_tax2
+from orders where id=?]==]);
+			_stmt_calc_order = db.prepare([==[
+select quantity, weight, price, price_decimals, discount_pct,
+sales_tax1_pct, sales_tax2_pct, product_id, description
+from orders_lines where order_id=?]==]);
+		}
+	}
+
+	function calc_one_line(calc_line){
+		calc_line.clear_preserving_tax_flags();
+		calc_line.quantity = _stmt_calc_order.col(0);
+		calc_line.weight = _stmt_calc_order.col(1);
+		calc_line.price = _stmt_calc_order.col(2);
+		calc_line.price_decimals = _stmt_calc_order.col(3);
+		calc_line.discount_pct = _stmt_calc_order.col(4);
+		calc_line.sales_tax1_pct = _stmt_calc_order.col(5);
+		calc_line.sales_tax2_pct = _stmt_calc_order.col(6);
+
+		//collect weight before calc, after calc it will have an incorrect value
+		//because we are not suppling unit_weight
+		weight_total += calc_line.weight;
+
+		calc_line.calc();
+
+		++lines_count;
+		subtotal_amt += calc_line.line_subtotal;
+		discount_amt += calc_line.discount_amt;
+		sales_tax1_amt += calc_line.sales_tax1_amt;
+		sales_tax2_amt += calc_line.sales_tax2_amt;
+		total_amt += calc_line.line_total;
+	}
+	
+	function number_format_trim(num){
+		local snum = math.number_format(num);
+		return snum;
+	}
+
+	function calc_order_totals(db, order_id, calc_line, vec_lines=null)
+	{
+		clear(); //reset totals
+		create_stmt_calc_order(db);
+		local number_format = math.number_format;
+
+		_stmt_get_tax_usage.reset();
+		_stmt_get_tax_usage.bind(1, order_id);
+		if(!_stmt_get_tax_usage.next_row()) return;
+
+		calc_line.tax_exempt = _stmt_get_tax_usage.col(0) == 1;
+		calc_line.use_sales_tax2 = _stmt_get_tax_usage.col(1) == 1;
+		_stmt_get_tax_usage.reset();
+
+		_stmt_calc_order.reset();
+		_stmt_calc_order.bind(1, order_id);
+		while(_stmt_calc_order.next_row())
+		{
+			calc_one_line(calc_line);
+			if(vec_lines)
+			{
+				local vec_str = [];
+				vec_str.push(_stmt_calc_order.col(7));
+				vec_str.push(_stmt_calc_order.col(8));
+				vec_str.push(number_format_trim(calc_line.quantity));
+				vec_str.push(number_format(calc_line.price, calc_line.price_decimals));
+				vec_str.push(number_format_trim(calc_line.discount_pct));
+				vec_str.push(number_format_trim(calc_line.sales_tax1_pct));
+				vec_str.push(number_format_trim(calc_line.sales_tax2_pct));
+				vec_str.push(number_format(calc_line.first_total, calc_line.price_decimals));
+				vec_lines->push(vec_str);
+			}
+		}
+		//sqlite3_reset(_stmt_calc_order);
+	}
+
+	function getPdfOrder(db, id, calc_line, lang, logoImg=null)
+	{
+		local str;
+		local  pdf_order = new My_PDF_Order(db, lang);
+		pdf_order.do_init();
+		if(logoImg) pdf_order.logoFileName = logoImg;
+		pdf_order.water_mark = "T H I S   I S   A   D E M O";
+		local stmt = db.prepare("select * from orders where id=?", id);
+		if(stmt.next_row())
+		{
+			local order_type_id = stmt.col("order_type_id");		
+			pdf_order.labelNumber = db.exec_get_one(
+				format("select description_to_print from order_types where id=%d",
+					order_type_id));
+			local order_number = stmt.col("order_number");
+			pdf_order.strNumber = stmt.col("series");
+			pdf_order.strNumber += "/";
+			pdf_order.strNumber += order_number;
+			pdf_order.strDate = stmt.get("order_date");
+			pdf_order.strEntity.push(stmt.get("entity_name"));
+			pdf_order.strEntity.push(stmt.col("entity_address"));
+			pdf_order.strEntity.push(stmt.col("entity_phone"));
+			pdf_order.strEntity.push(stmt.get("entity_tax_number"));
+		}
+		calc_order_totals(db, id, calc_line, pdf_order.strLines);
+		pdf_order.strTotals.push(math.number_format(subtotal_amt));
+		pdf_order.strTotals.push(math.number_format(sales_tax1_amt));
+		pdf_order.strTotals.push(math.number_format(sales_tax2_amt));
+		pdf_order.strTotals.push(math.number_format(total_amt));
+
+		pdf_order.orderTable(31);
+		//pdf_order.SetCompression(false);
+		return pdf_order.Output("doc-order.pdf", 'S');
+	}
+}
+
+class MyCalcOrderTotals
+{
+	order_totals = null;
+	calc_line = null;
+	db = null;
+    
+	constructor(adb)
+	{
+		db = adb;
+		calc_line = new CalcOrderLine();
+		order_totals = new CalcOrderTotals();
+	}
+
+	function calc_total(id){
+		order_totals.calc_order_totals(db, id, calc_line);
+		return order_totals.total_amt;
+	}
+}
+
+class DB_Orders extends DB_Manager {
+	constructor(){
+		base.constructor("orders", [
+		"order_type_id", "series", "order_number", "entity_order_number",
+		"entity_id", "entity_name", "entity_address",
+		"entity_phone", "entity_zip", "entity_city",
+		"entity_state", "entity_country", "entity_tax_number",
+		"entity_use_sales_tax2", "entity_sales_tax_exempt",
+		"order_date", "payment_type_id", "notes",
+		"cash", "tags", "order_valid_till_date",
+		"irpf_pct_retention"]);
+	}
+
+	function sql_search_list(qs_tbl, post_tbl){
+		local so = get_search_options(post_tbl);
+		checkQueryStringSAB(qs_tbl, so);
+		local mf = blob();
+		
+		mf.write("SELECT o.id, o.order_date, ot.code, o.series, o.order_number,",
+			//" o.entity_name, get_order_total(o.id) as total_amt, pt.code "
+			" o.entity_name, ",
+			" (subtotal + total_sales_tax1 + total_sales_tax2) as total_amt, ",
+			" pt.code ",
+			" FROM ((orders AS o LEFT JOIN payment_types as pt ON o.payment_type_id = pt.id) ",
+			" JOIN  order_types as ot ON o.order_type_id = ot.id) WHERE 1=1 ");
+
+		if (so.sales || so.buys) {
+			if (so.sales) mf.write(" and ot.group_order = 'S' ");
+			else if (so.buys) mf.write(" and ot.group_order = 'B' ");
+		}
+
+		if (so.payment_type_id && so.payment_type_id != 0)
+			mf.write(" and o.payment_type_id = " , so.payment_type_id);
+
+		if (so.group_id && so.group_id != 0)
+			mf.write(" and o.order_type_id = " , so.group_id , " ");
+
+		local search_str = escape_sql_like_search_str(so.search_str);
+		if (so.entity_id && so.entity_id != 0) mf.write(" and o.entity_id =" , so.entity_id);
+		else
+		{
+			if (so.product_id && so.product_id != 0){
+				mf.write(" and o.id in( select order_id from orders_lines as ol ");
+
+				if (so.sales || so.buys){
+					mf.write(", (orders as o join order_types as ot on o.order_type_id = ot.id and ot.group_order = ");
+					if (so.sales) mf.write(" 'S' )");
+					else if (so.buys) mf.write(" 'B' )");
+				}
+
+				mf.write("where ol.product_id =", so.product_id);
+				if (so.sales || so.buys) mf.write(" and ol.order_id = o.id ");
+				mf.write(" order by ol.id desc ");
+				if (so.query_limit != 0) mf.write(" limit " , so.query_limit);
+				mf.write(")")
+			}
+			else if (search_str && search_str.len() > 0) {
+				if (so.products){
+					mf.write(" and o.id in ( select order_id from orders_lines where ",
+						" description like "" , search_str , "" order by id desc limit " , so.query_limit , ")");
+				}
+				else mf.write(" and ");
+				
+				if (so.notes) mf.write(" o.notes ");
+				else if (so.date) mf.write(" o.order_date ");
+				//lo_search_str = escapeSqlLikeSearchStr(dbDate(search_str))
+				//table.insert(sql, " and order_date = (("")
+				else if (so.total) mf.write(" o.total_amt ");
+				else  mf.write(" o.entity_name ");
+
+				mf.write(" like '" , search_str , "' ");
+			}
+		}
+
+		if (so.order_by_modification) mf.write(" and o.mdate is not null order by o.mdate desc ");
+		else if (so.order_by_creation) mf.write(" order by o.id desc ");
+		else mf.write(" order by o.order_date desc, o.id desc ");
+	    
+		if (so.query_limit && so.query_limit != 0) mf.write(" limit " , so.query_limit);
+		//debug_print(tostring(mf), "\n")
+		return  mf.tostring();
+	}
+
+	function get_bar_chart_statistics_sql_core(mf, sab, speriode, speriode_count, strPU1, strPU2){
+		mf.write("SELECT ", speriode, " as qm, sum(subtotal + total_sales_tax1 + total_sales_tax2) as q, '",
+			sab, "' as sab ", strPU1, " FROM orders WHERE order_type_id IN(SELECT * FROM order_types_",
+			(sab == "S" ? "sell" : "buy"), "_payment) AND order_date >= ", speriode_count, " GROUP BY qm ",
+			strPU2);
+	}
+
+	function sql_bar_chart_statistics(sab, periode_count=12, periode_type=TimePeriode.is_months, paidUnpaid=false)
+	{
+		local strPU1, strPU2;
+		local mf = blob();
+		if(paidUnpaid)
+		{
+			strPU1 = ", payment_type_id = 1 as pt ";
+			strPU2 = ", pt ";
+		}
+		else strPU1 = strPU2 = "";
+		
+		local rc = get_sql_bar_chart_statistics_periodes(periode_count, periode_type);
+		local speriode = rc[0],  speriode_count = rc[1];
+
+		if(sab == "S" || sab == "B")
+			get_bar_chart_statistics_sql_core(mf, sab, speriode, speriode_count, strPU1, strPU2);
+		else {
+			mf.write("select qm, q, sab ");
+			if(paidUnpaid) mf.write(strPU2);
+			mf.write(" from (");
+			get_bar_chart_statistics_sql_core(mf, "S", speriode, speriode_count, strPU1, strPU2);
+			mf.write(" UNION ALL ");
+			get_bar_chart_statistics_sql_core(mf, "B", speriode, speriode_count, strPU1, strPU2);
+			mf.write(") as t ");
+		}
+
+		mf.write(" order by qm, sab");
+		if(paidUnpaid) mf.write(strPU2);
+
+		//printf("%d : %d\n%s\n", periode, periode_count, out_sql.cstr());
+		return mf.tostring();
+	}
+
+	function sql_list(qs_tbl, post_tbl){
+		if (qs_tbl.get("search", false)) return sql_search_list(qs_tbl, post_tbl);
+		else if (qs_tbl.get("history", false)){
+			local htype = qs_tbl.get("htype", 0);
+			local query_limit = qs_tbl.get("query_limit", 50).tointeger();
+			return DB_Entities.sales_history_sql(htype, query_limit, qs_tbl.history);
+		}
+		else if (qs_tbl.get("statistics", false)){
+			local periode_count = qs_tbl.get("periode_count", 12).tointeger();
+			local periode_type = getStatisticsPeriodeType(qs_tbl.get("periode_type", "months"));
+			local sab = qs_tbl.get("sab", "S");
+			return sql_bar_chart_statistics(sab, periode_count, periode_type);
+		}
+		else if (qs_tbl.get("print_list", false)){
+		}
+	}
+}
+
+db_ourbiz_tables.orders <-  new DB_Orders();
+
+//
+// products
+//
+
+class DB_Products extends DB_Manager {
+	constructor(){
+		base.constructor("products", [
+		"buy_description","buy_discount","buy_notes",
+		"buy_other_costs","buy_price",	"buy_quantity_min","group_id",
+		"image_id","is_active","measure_unit_id","price_decimals",
+		"price_formula","reference_code","sales_tax_id","sell_description",
+		"sell_markup","sell_notes","sell_price","sell_quantity_min","show_on_buys",
+		"show_on_sales","show_on_web","show_price_on_web","stock_max","stock_min",
+		"supplier_code","tags","units_by_package","warranty_id","weight",
+		"sell_without_stock"]);
+	}
+
+	function db_action(db, data){
+		mkEmptyWhenZero(data, ["warranty_id",  "group_id",  "measure_unit_id",  "image_id",  "sales_tax_id"]);
+		return base.db_action(db, data);
+	}
+
+	function sql_search_list(qs_tbl, post_tbl){
+		local so = get_search_options(post_tbl);
+		checkQueryStringSAB(qs_tbl, so);
+		local mf = blob();
+		
+		mf.write([==[
+select p.id, 
+	p.reference_code,
+	p.sell_description,
+	ifnull(p.kit,  0)  as kit,
+		round((p.sell_price * (1 + (st.rate1/100.0))),p.price_decimals) as price_taxed,
+		round(p.sell_price, p.price_decimals) as price,
+	round(case when p.kit > 0 then p.kit_onhand else p.quantity_onhand end, 4) as quantity_onhand,
+	p.is_active, price_date,
+	p.image_id
+]==])
+		if (so.with_images) mf.write(", thumbnail, mime_type ");
+		mf.write(" from (products_onhand as p left join sales_tax_rates as st on p.sales_tax_id = st.id) ");
+		if (so.with_images) mf.write(" left join images as i on p.image_id = i.id ");
+		mf.write(" where ");
+
+		if ( (!so.group_id) && (!so.entity_id) && (! (so.search_str && (so.search_str.len() > 0)))){
+			//special case where we get the latest entities that made any transaction
+			mf.write(" p.id in(select distinct product_id from orders_lines where order_id in (select o.id from orders as o ");
+		
+			if (so.sales || so.buys){
+				mf.write(", order_types as ot where o.order_type_id = ot.id and ot.group_order =");
+				if (so.sales) mf.write("'S'");
+				else if (so.buys) mf.write("'B'");
+			}
+
+			mf.write(" order by o.id desc");
+			if (so.query_limit && so.query_limit != 0) mf.write(" limit " , so.query_limit);
+			mf.write(")) order by 3");
+			return mf.tostring();
+		}
+
+		if (so.sales && so.buys) mf.write(" 1=1 ");
+		else if (so.sales || so.buys){
+			if (so.sales) mf.write(" show_on_sales = 1 ");
+			else if (so.buys) mf.write(" show_on_buys = 1 ");
+		}
+		else mf.write(" 1=1 ");
+
+		if (so.group_id && so.group_id != 0)
+			mf.write(" and p.group_id=" , so.group_id , " ");
+
+		if (so.active) mf.write(" and p.is_active = 1 ");
+		
+		if (so.only_prices_older){
+			//local adate = parse_date(optNum)
+			//mf.write(" and p.price_update_date < '" ,
+			//string.format("%d-%.02d-%.02d", adate.year, adate.month, adate.day) + "' ");
+		}
+
+		local search_str = escape_sql_like_search_str(so.search_str);
+
+		if (so.entity_id && so.entity_id != 0){
+			mf.write([==[
+and p.id in(
+select product_id from orders_lines where order_id in (
+	select id from orders where entity_id = " , so.entity_id
+	order by id desc)) ]==]);
+		}
+		else if (search_str && search_str.len() > 0){
+			if (so.id && so.id != 0) mf.write(" and p.id = " , so.search_str.tointeger());
+			else
+			{
+				if (so.entities){
+					mf.write(" and p.id in(",
+						"select product_id from orders_lines where order_id in (",
+						"select id from orders where entity_id in (",
+						"select id from entities where name like "" , search_str, "" ",
+						"or company like "" , search_str, "" order by id desc ))) ");
+				}
+				else mf.write(" and ");
+				if (so.notes){
+					if (so.buys) mf.write(" buy_notes ");
+					else mf.write(" sell_notes ");
+				}
+				else if (so.reference) mf.write(" reference_code ");
+				else mf.write(" p.sell_description ");
+
+				mf.write(" like '" , search_str , "' ");
+			}
+		}
+
+		if (so.order_by_modification) mf.write(" p.mdate is not null order by p.mdate desc ");
+		else if (so.order_by_creation) mf.write(" 1=1 order by id desc ");
+		else mf.write(" order by 3 ");
+
+		if (so.query_limit && so.query_limit != 0) mf.write(" limit " , so.query_limit);
+		//debug_print(tostring(mf), "\n")
+		return  mf.tostring();
+	}
+
+	function sql_list(qs_tbl, post_tbl){
+		if (qs_tbl.get("search", false)) return sql_search_list(qs_tbl, post_tbl);
+		else if (qs_tbl.get("past_products", false)) return DB_Entitles.past_products_sql(qs_tbl.past_products);
+		else if (qs_tbl.get("history", false)) {
+			local htype = qs_tbl.get("htype", 0);
+			local query_limit = qs_tbl.get("query_limit", 50).tointeger();
+			return DB_Entities.sales_history_sql(htype, query_limit, qs_tbl.history);
+		}
+		else if (qs_tbl.get("statistics", false)){
+			local periode_count = qs_tbl.get("periode_count", 12).tointeger();
+			local periode_type = getStatisticsPeriodeType(qs_tbl.periode_type);
+			local sab = qs_tbl.get("sab", "S");
+			return DB_Entities.sql_bar_chart_statistics(tonumber(qs_tbl.statistics), sab, periode_count, periode_type);
+		}
+		else if (qs_tbl.get("print_list", false)){
+			return [==[
+select 
+    p.id  as 'id|ID|6|R', 
+    case when p.user_code isnull then ' ' else p.user_code end as 'reference|Reference|9', 
+    p.sell_description as 'sell_description|Description|-1', 
+    cast(case when p.kit isnull then 0 else kit end as text) as 'kit|Kit|4|C', 
+    round((p.sell_price * (1 + (st.rate1/100.0))),p.price_decimals) as 'price_taxed|Price+V.A.T.|12|R|M', 
+    round(case when p.kit > 0 then p.kit_onhand else p.quantity_onhand end, 4) as 'quantity_onhand|Onhand|10|R|N' 
+from products_onhand as p left join sales_tax_rates as st 
+on p.sales_tax_id = st.id order by 3
+]==];
+		}
+		else if (qs_tbl.get("pdf", false)){
+			local clipped = qs_tbl.get("clipped", false);
+			local pdf = new PdfSqlTable();
+			pdf.page_title = "Products List";
+			pdf.water_mark = "T H I S   I S   A   D E M O";
+
+			local sql = [==[
+select 
+    p.id  as 'id|ID|6|R', 
+    case when p.user_code isnull then ' ' else p.user_code end as 'reference|Reference|9', 
+    p.sell_description as 'sell_description|Description|-1', 
+    cast(case when p.kit isnull then 0 else kit end as text) as 'kit|Kit|4|C', 
+    round((p.sell_price * (1 + (st.rate1/100.0))),p.price_decimals) as 'price_taxed|Price+V.A.T.|12|R|M', 
+    round(case when p.kit > 0 then p.kit_onhand else p.quantity_onhand end, 4) as 'quantity_onhand|Onhand|10|R|N' 
+from products_onhand as p left join sales_tax_rates as st 
+on p.sales_tax_id = st.id order by 3
+]==]
+			local db = getOurbizDB();
+			local mf = blob();
+			pdf.GetPDF(db, sql, clipped, mf);
+			qs_tbl._doc_pdf_ <- mf;
+			return true;
+		}
+	}
+}
+
+db_ourbiz_tables.products <- new DB_Products();
+
+//
+// images
+//
+
+class DB_Images extends DB_Manager {
+	constructor(){
+		base.constructor("images", ["mime_type", "name", "description", "group_set", "image", "thumbnail"]);
+	}
+	
+	function sql_list(qs_tbl, post_tbl){
+		local so = get_search_options(post_tbl);
+		local mf = blob();
+		mf.write("select id, name, mime_type, group_set ");
+		if (so.with_images) mf.write(", thumbnail ");
+		mf.write(" from images where 1=1 ");
+		if ((so.search_str && so.len().search_str > 0) || so.image_id != 0){
+			local search_str = escape_sql_like_search_str(so.search_str);
+			if (so.image_id) mf.write(" and id=", so.image_id);
+			else if (so.id) mf.write(" and id=", so.search_str.tointeger());
+			else if (so.group_set) mf.write(" and group_set=", so.search_str.tointeger());
+			else if (so.description) mf.write(" and description like '", search_str, "' ");
+			else  mf.write(" and name like '", search_str, "' ");
+		}
+		mf.write(" order by name limit ", so.query_limit);
+		//debug_print(tostring(mf), "\n")
+		return  mf.tostring();
+	}
+	
+	function sql_get_one(req){
+		local mf = blob();
+		mf.write("select id, _version_, mime_type, name, description, group_set, cdate, mdate, length(image) as img_size ");
+		if (req.get("image_and_size", false)) mf.write(", image ");
+		mf.write("from ", table_name ," where id=?");
+		return  mf.tostring();
+	}
+}
+
+db_ourbiz_tables.images <- new  DB_Images();
+
+class DB_order_types extends DB_Manager {
+	constructor(){
+		base.constructor("order_types", ["is_active", "code", "description", "description_to_print",
+            "group_order", "is_expense", "is_incoming", "notes", "numbering",
+            "series", "show_prices", "show_sales_tax", "subgroup_order",
+            "with_credit", "with_inventory", "with_payment", "with_ordered",
+            "with_sales_tax", "with_sales_tax_included", "with_quote"]);
+	}
+	
+	function sql_list(qs_tbl, post_tbl){
+		if (qs_tbl.get("short_list", false)){
+			local sql = "select id, description from order_types where is_active = 1 ";
+			local group_order = qs_tbl.get("group_order", false);
+			if (group_order && (group_order == "S" || group_order == "B")){
+				sql = format("%s and group_order='%s' ", sql, group_order);
+			}
+			sql = format("%s order by group_order,subgroup_order", sql);
+			return sql;
+		}
+		else
+		{
+			return [==[
+SELECT
+    id,
+    code,
+    description,
+    with_payment,
+    with_inventory,
+    group_order,
+    subgroup_order,
+    is_active
+FROM order_types
+ORDER BY group_order,subgroup_order
+]==];
+		}
+	}
+}
+
+
+db_ourbiz_tables.order_types <- new DB_order_types();
+
+
+db_ourbiz_tables.measure_units <- new DB_Manager("measure_units");
+
+db_ourbiz_tables.payment_types <- new DB_Manager("payment_types", ["is_active", "code", "description", "payment_terms", "notes"]);
+
+function check_payment_terms(txt){
+	local init = 0;
+	local pct = 0.0;
+	txt.gmatch("(%d+)%s+(%d+%.?%d*)%D+(%d+)%s+(%S+)", function(n, v, p, pt){ 
+		// n ->decimal number expected
+		// v -> pct number expected
+		pct += v.tofloat();
+		// p -> integer number expected
+		// pt -> string expected
+		if (!(pt == "d" || pt == "w" || pt == "m" || pt == "dm")){
+			throw "Invalid paymment terms periode !";
+		}
+	});
+	//check for error
+	if (pct != 100.0) throw "Total percentage not equal to 100% !";
+}
+
+class DB_sales_tax_rates extends DB_Manager {
+	constructor(){
+		base.constructor("sales_tax_rates", ["is_active", "rate1", "rate2", "description"]);
+	}
+	
+	function sql_list(qs_tbl=null, post_tbl=null) {
+		return "select id,rate1,rate2,description,is_active from sales_tax_rates order by rate1";
+	}
+}
+
+db_ourbiz_tables.sales_tax_rates <- new DB_sales_tax_rates();
+ 
+db_ourbiz_tables.warranty_types <- new DB_Manager("warranty_types")
+
+
+function product_prices_list_sql (product_id){
+	product_id = product_id.tointeger();
+	return format([==[
+select id,quantity ,
+    markup_pct ,
+    discount_pct ,
+    price, mdate, cdate
+from product_prices
+where product_id = %d
+UNION ALL
+select 0 , sell_quantity_min, sell_markup, 0,sell_price , price_date , cdate
+from products
+where id = %d
+order by quantity
+]==], product_id, product_id);
+}
+
+function products_kit_list_sql (kit_id, partOf=false){
+	kit_id = kit_id.tointeger();
+	local str1, str2;
+	if (partOf){
+		str1 = format("pk.product_id=%d", kit_id);
+		str2 = "and pk.kit_id = p.id order by p.sell_description";
+	}
+	else
+	{
+		str1 = format("pk.kit_id=%d", kit_id);
+		str2 = "and pk.product_id = p.id order by p.sell_description";
+	}
+	return format([==[
+select pk.id, 
+	p.id,
+	p.sell_description,
+	pk.quantity, 
+	round((p.sell_price*pk.quantity),4) as amount,
+	p.quantity_onhand
+from product_kits as pk, products as p
+where %s %s
+]==], str1, str2);
+}
+
+function products_kit_details_get_one (kit_id){
+	kit_id = kit_id.tointeger();
+	return format([==[
+select count(*) as nproducts, sum(p.sell_price * pk.quantity) as amt_total
+from product_kits as pk left join products as p on pk.product_id = p.id
+where pk.kit_id = %d]==], kit_id);
+}
+
+constants.SLE <- "\xff";
+
+function add2sle(out_result, str){
+	str = str.tostring();
+	out_result.write(SQLite3Stmt.get_sle_size(str.len()), str);
+}
+
+function dump_group_tree_childs(parent, out_result, parent_map, data_map){
+	for(int_t iter=0, count = parent_map.len(); iter < count; ++iter){
+		if (parent_map[iter][0] == parent){
+			for (local found=iter, parent_count = parent_map.len(); found < parent_count; ++found){
+				local map = parent_map[found];
+				local id = map[1];
+				local myparent = map[0];
+				//debug_print(myparent, "\t", parent, "\n");
+				if (myparent != parent) break;
+				out_result.write("[");
+				add2sle(out_result, id);
+				add2sle(out_result, myparent);
+				add2sle(out_result, data_map[id]);
+				out_result.write(SLE, "]");
+				dump_group_tree_childs(id, out_result, parent_map, data_map);
+			}
+			break;
+		}
+	}
+}
+
+function group_dump_data(db, out_result, tbl){
+	out_result.clear();
+	local parent_map = [];
+	local  group_map = {};
+	local id, parent_id;
+	local stmt = db.prepare(format("select id, parent_id, description from %s order by 3", tbl));
+	while (stmt.next_row()) {
+		id = stmt.col(0);
+		parent_id = stmt.col(1);
+		if (type(parent_id) == "string") parent_id = 0;
+		//debug_print(parent_id, "\t", id, "\n");
+		parent_map.push([parent_id == SQLite3.Null ? null : parent_id, id]);
+		group_map[id] <- stmt.col(2);
+	}
+	parent_map.sort(@(a,b) a[0] <=> b[0] );
+	out_result.write("[[");
+	add2sle(out_result, "id");
+	add2sle(out_result, "parent_id");
+	add2sle(out_result, "description");
+	out_result.write(SLE, "]");
+	dump_group_tree_childs(0, out_result, parent_map, group_map);
+	out_result.write("]");
+}
+
+function ourbizDbMobile(request){
+	local data = {};
+	data.page_name = "list_products";
+	local query_string = request.info.query_string;
+	
+	local db = getOurbizDB();
+	local sql = "select id, reference_code, sell_description, sell_price, image_id from products ";
+	local search_str;
+	if (query_string) search_str = request.get_var(query_string, "search_str");
+	if (search_str){
+		sql = format("%s where sell_description like ? ", sql);
+	}
+	sql += format("%s limit 50", sql);
+	local stmt = db.prepare(sql);
+	//debug_print(sql, "\n")
+	if (search_str){
+		stmt.bind(1, escape_sql_like_search_str(search_str));
+	}
+	local result = getDbListFromStmt(stmt);
+	data.rows <- result[0];
+	local mFile = gmFile;
+	mFile.clear();
+	data.mix_write <- function(str){ if(str) mFile.write(str); };
+	fillTemplate("mobile-list.tpl", data, AT_DEV_DBG);
+	request.print(format("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %d\r\n\r\n", mFile.len()));
+	request.write_blob(mFile);
+	return true;
+}
+
+function ourbizDbGetList(request){
+	local query_string = request.info.query_string
+	if (query_string){
+		local db = getOurbizDB();
+		local qs_tbl = parse_qs_to_table(query_string);
+		local list = qs_tbl.get("list", null);
+		local sab = qs_tbl.get("sab", "S");
+		local isPost = request.info.request_method == "POST";
+		local sql, post_tbl, data;
+		if (isPost) post_tbl = get_post_fields(request, 1024);
+		else post_tbl = {};
+	
+		if (!post_tbl.get("query_limit", false)) post_tbl.query_limit <- 50;
+		gmFile.clear();
+		
+		if (list == "entity_groups") group_dump_data(db, gmFile, "entity_groups");
+		else if (list == "product_groups") group_dump_data(db, gmFile, "product_groups");
+		else if (list == "config") sql = "select key,value from config";
+		else if (db_ourbiz_tables.get(list, false)){
+			sql = db_ourbiz_tables[list].sql_list(qs_tbl, post_tbl);
+			local doc_pdf = qs_tbl.get("_doc_pdf_", false);
+			if (doc_pdf){
+				request.print(format([==[
+HTTP/1.1 200 OK
+Content-type: application/pdf
+Content-Disposition: attachment; filename=%s-list.pdf
+Content-Length: %d
+
+]==], list, doc_pdf.len()));
+				if(doc_pdf instanceof blob) request.write_blob(doc_pdf);
+				else request.print(doc_pdf);
+				return true;
+			}
+		}
+		
+		if (sql){
+			local stmt = db.prepare(sql);
+			//debug_print(sql, "\n", db.error_message(), "\n")
+			data = stmt.asSleArray();
+			stmt.finalize();
+		}
+		else if (gmFile.len() > 0){
+			data = gmFile.tostring();
+		}
+		
+		if (data){
+			//using string.format with binary data gives wrong results
+			gmFile.clear()
+			gmFile.write("HTTP/1.1 200 OK\r\nContent-type: text/plain; charset=x-user-defined\r\nContent-Length: ", data.len(), "\r\n\r\n", data);
+			request.write_blob(gmFile);
+			return true;
+		}
+	}
+	return false;
+}
+
+function ourbizDbGetOne(request){
+	local query_string = request.info.query_string;
+	if (query_string){
+		local db = getOurbizDB();
+		local tbl_qs = {}, tbl_keys = [];
+		parse_qs_to_table_k(query_string, tbl_qs, tbl_keys);
+		if (tbl_keys.len() == 0) return false;
+		local tbl = tbl_keys[0];
+		local rec_id = tbl_qs[tbl];
+		local sql, data;
+		
+		gmFile.clear()
+		
+		if (tbl == "orders"){
+			if (request.get_var(query_string, "with_lines")){
+				sql = "select * from orders where id=?";
+				local stmt = db.prepare(sql);
+				stmt.bind(1, rec_id);
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();
+				sql = "select id, product_id, description, quantity, price, 0 as sub_total from orders_lines where order_id=?";
+				stmt = db.prepare(sql);
+				stmt.bind(1, rec_id);
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();
+				sql = null;
+			}
+			else if (request.get_var(query_string, "line_calculated")){
+				sql = "select * from orders_lines where id=?";
+			}
+		}
+		else if (tbl == "products"){
+			local product_aux_data = request.get_var(query_string, "product_aux_data");
+			local product_for_edit = request.get_var(query_string, "product_for_edit");
+			if (product_aux_data){
+				local stmt = db.prepare(db_ourbiz_tables.sales_tax_rates.sql_short_list(tbl_qs));
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();
+				stmt = db.prepare("select id, description from measure_units where is_active=1 order by description");
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();
+				stmt = db.prepare("select id, description from warranty_types where is_active=1 order by description");
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();
+			}
+			else if (product_for_edit){
+				local stmt = db.prepare("select * from products where id=?");
+				stmt.bind(1, rec_id);
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();
+				
+				stmt = db.prepare(product_prices_list_sql(rec_id));
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();
+				
+				stmt = db.prepare(products_kit_list_sql(rec_id));
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();			
+
+				stmt = db.prepare(products_kit_details_get_one(rec_id));
+				gmFile.write(stmt.asSleArray());
+				stmt.finalize();
+			}
+			else sql = "select * from products where id=?";
+		}
+		else if (tbl == "config") sql = "select * from config where id=?";
+		else if (db_ourbiz_tables.get(tbl, false)) sql = db_ourbiz_tables[tbl].sql_get_one(tbl_qs);
+		
+		if (sql){
+			local stmt = db.prepare(sql);
+			stmt.bind(1, rec_id);
+			data = stmt.asSleArray();
+			//debug_print(rec_id, "\t", sql, "\t", data.len(), "\t", data, "\n")
+			stmt.finalize();
+		}
+		else if (gmFile.len() > 0) data = gmFile.tostring();
+		
+		if (data){
+			//using string.format with binary data gives wrong results
+			gmFile.clear();
+			gmFile.write("HTTP/1.1 200 OK\r\nContent-type: text/plain; charset=x-user-defined\r\nContent-Length: ", data.len(), "\r\n\r\n", data);
+			request.write_blob(gmFile);
+			return true;
+		}
+	}
+	return false;
+}
+
+function ourbizDbGetBin(request){
+	local query_string = request.info.query_string;
+	if (query_string){
+		local db = getOurbizDB();
+		local image = request.get_var(query_string, "image");
+		local thumbnail = request.get_var(query_string, "thumbnail");
+		local stmt;
+		gmFile.clear();	
+
+		if (image){
+			gmFile.write("select ");
+			if (thumbnail) gmFile.write("thumbnail");
+			else gmFile.write("image");
+
+			gmFile.write(", mime_type from images where id=",  image.tointeger());
+			stmt = db.prepare(gmFile.tostring());
+		}
+		
+		if (stmt){
+			local result = stmt.step() == stmt.SQLITE_ROW;
+			if (result){
+				local data = stmt.col(0);
+				local mime = stmt.col(1);
+				//using string.format with binary data gives wrong results
+				gmFile.clear();
+				gmFile.write("HTTP/1.1 200 OK\r\nContent-type: ", mime, "\r\nContent-Length: ", data.len(), "\r\n\r\n", data);
+				request.write_blob(gmFile);
+			}
+			stmt.finalize();
+			return result;
+		}
+	}
+	return false;
+}
+
+function ourbizDbAction(request){
+	local isPost = request.info.request_method == "POST";
+	if (isPost){
+		local data = get_post_fields(10*1024);
+		local db = getOurbizDB();
+		local tbl = data.get("__table__", null);
+		local action = data.get("__action__", null);
+		local result, err_msg;
+		//debug_print(tbl, "\n", action, "\n", data.__id__, "\n")
+		gmFile.clear();
+		local db_manager = db_ourbiz_tables.get(tbl, null);
+		if (db_manager){
+			try {
+				result = db_manager.db_action(db, data);
+			} catch(e){
+				err_msg = e;
+			}
+		}
+		if (result){
+			gmFile.clear();
+			gmFile.write("[[");
+			if (action == "insert") add2sle(gmFile, "id");
+			else add2sle(gmFile, "changes");
+
+			gmFile.write(SLE, "][");
+			add2sle(gmFile, result);
+			gmFile.write(SLE, "]]");
+			data = gmFile.tostring();
+		}
+		else if (err_msg) data = err_msg;
+		else data = null;
+
+		//debug_print(data, "\n")
+		if (data){
+			//using string.format with binary data gives wrong results
+			gmFile.clear();
+			gmFile.write("HTTP/1.1 200 OK\r\nContent-type: text/plain; charset=x-user-defined\r\nContent-Length: ", data.len(), "\r\n\r\n", data);
+			//debug_print(tostring(gmFile), "\n")
+			request.write_blob(gmFile);
+			return true;
+		}
+	}
+	return false;
+}
+
+

+ 125 - 0
ourbiz/sales-tax-window.nut

@@ -0,0 +1,125 @@
+class SalesTaxRatesEditWindow extends MyBaseWindow {
+	grid=null;
+	editGroup=null;
+	db_sales_tax_rates_id=null;
+	db_sales_tax_rates_cdate=null;
+	db_sales_tax_rates_mdate=null;
+	db_sales_tax_rates_rate1=null;
+	db_sales_tax_rates_rate2=null;
+	db_sales_tax_rates_is_active=null;
+	db_sales_tax_rates_description=null;
+	dbAction=null;
+	btnDbAction= null;
+	db_map = null;
+	
+constructor() {
+	base.constructor(10, 50, 500, 385, _tr("Sales Tax Rates List / Edit"));
+	db_map = {};
+	
+	dbAction = new Fl_Button(0, 0, 100, 25, _tr("Action"));
+	btnDbAction = new Fl_Button(0, 0, 100, 25, _tr("Action"));
+	begin();
+	this->box(FL_FLAT_BOX);
+	this->color(FL_BACKGROUND_COLOR);
+	this->selection_color(FL_BACKGROUND_COLOR);
+	this->labeltype(FL_NO_LABEL);
+	this->labelfont(0);
+	this->labelsize(16);
+	this->labelcolor(FL_FOREGROUND_COLOR);
+	this->align((FL_ALIGN_TOP));
+	this->when(FL_WHEN_RELEASE);
+	{ grid = new Fl_Data_Table(5, 5, 490, 200);
+	  grid->tooltip(_tr("List of available sales tax"));
+	  grid->type(3);
+	  grid->box(FL_NO_BOX);
+	  grid->color(FL_BACKGROUND2_COLOR);
+	  grid->selection_color(FL_SELECTION_COLOR);
+	  grid->labeltype(FL_NO_LABEL);
+	  grid->labelfont(0);
+	  grid->labelsize(16);
+	  grid->labelcolor(FL_FOREGROUND_COLOR);
+	  grid->textsize(16);
+	  grid->align((FL_ALIGN_BOTTOM));
+	  grid->when(FL_WHEN_RELEASE_ALWAYS);
+	  Fl_Group.current()->resizable(grid);
+	} // Fl_Data_Table* grid
+	{ editGroup = new Fl_Group(5, 215, 490, 165);
+	  editGroup->box(FL_ENGRAVED_BOX);
+	  editGroup->color(246);
+	  editGroup->labelsize(16);
+	  editGroup->align((FL_ALIGN_RIGHT));
+	  { db_sales_tax_rates_id = new Fl_Output(15, 240, 82, 26, _tr("ID"));
+	    db_sales_tax_rates_id->tooltip(_tr("The unique identifier"));
+	    db_sales_tax_rates_id->labelsize(16);
+	    db_sales_tax_rates_id->textsize(16);
+	    db_sales_tax_rates_id->align((FL_ALIGN_TOP_LEFT));
+	    add_input_field_to_map("sales_tax_rates", "id", db_sales_tax_rates_id);
+	  } // Fl_Output* db_sales_tax_rates_id
+	  { db_sales_tax_rates_cdate = new Fl_Output(115, 240, 120, 25, _tr("CDate"));
+	    db_sales_tax_rates_cdate->tooltip(_tr("The creation date"));
+	    db_sales_tax_rates_cdate->labelsize(16);
+	    db_sales_tax_rates_cdate->textsize(16);
+	    db_sales_tax_rates_cdate->align((FL_ALIGN_TOP_LEFT));
+	    add_input_field_to_map("sales_tax_rates", "cdate", db_sales_tax_rates_cdate);
+	  } // Fl_Output* db_sales_tax_rates_cdate
+	  { db_sales_tax_rates_mdate = new Fl_Output(255, 240, 120, 25, _tr("MDate"));
+	    db_sales_tax_rates_mdate->tooltip(_tr("The modification date"));
+	    db_sales_tax_rates_mdate->labelsize(16);
+	    db_sales_tax_rates_mdate->textsize(16);
+	    db_sales_tax_rates_mdate->align((FL_ALIGN_TOP_LEFT));
+	    add_input_field_to_map("sales_tax_rates", "mdate", db_sales_tax_rates_mdate);
+	  } // Fl_Output* db_sales_tax_rates_mdate
+	  { db_sales_tax_rates_rate1 = new Fl_Float_Input(15, 295, 82, 25, _tr("V.A.T. %"));
+	    db_sales_tax_rates_rate1->tooltip(_tr("Main sales tax percentage"));
+	    db_sales_tax_rates_rate1->type(1);
+	    db_sales_tax_rates_rate1->labelsize(16);
+	    db_sales_tax_rates_rate1->textfont(1);
+	    db_sales_tax_rates_rate1->textsize(16);
+	    db_sales_tax_rates_rate1->align((FL_ALIGN_TOP_LEFT));
+	    add_input_field_to_map("sales_tax_rates", "rate1", db_sales_tax_rates_rate1);
+	  } // Fl_Float_Input* db_sales_tax_rates_rate1
+	  { db_sales_tax_rates_rate2 = new Fl_Float_Input(115, 295, 82, 25, _tr("R.E. %"));
+	    db_sales_tax_rates_rate2->tooltip(_tr("Secondary sales tax percentage"));
+	    db_sales_tax_rates_rate2->type(1);
+	    db_sales_tax_rates_rate2->labelsize(16);
+	    db_sales_tax_rates_rate2->textfont(1);
+	    db_sales_tax_rates_rate2->textsize(16);
+	    db_sales_tax_rates_rate2->align((FL_ALIGN_TOP_LEFT));
+	    add_input_field_to_map("sales_tax_rates", "rate2", db_sales_tax_rates_rate2);
+	  } // Fl_Float_Input* db_sales_tax_rates_rate2
+	  { db_sales_tax_rates_is_active = new Fl_Check_Button(255, 294, 100, 23, _tr("Active"));
+	    db_sales_tax_rates_is_active->tooltip(_tr("We can deactivate instead of delete it"));
+	    db_sales_tax_rates_is_active->down_box(FL_DOWN_BOX);
+	    db_sales_tax_rates_is_active->labelsize(16);
+	    add_input_field_to_map("sales_tax_rates", "is_active", db_sales_tax_rates_is_active);
+	  } // Fl_Check_Button* db_sales_tax_rates_is_active
+	  { db_sales_tax_rates_description = new Fl_Input(15, 345, 350, 25, _tr("Description"));
+	    db_sales_tax_rates_description->tooltip(_tr("A friendly description to identify this tax"));
+	    db_sales_tax_rates_description->labelsize(16);
+	    db_sales_tax_rates_description->textfont(1);
+	    db_sales_tax_rates_description->textsize(16);
+	    db_sales_tax_rates_description->align((FL_ALIGN_TOP_LEFT));
+	    add_input_field_to_map("sales_tax_rates", "description", db_sales_tax_rates_description);
+	  } // Fl_Input* db_sales_tax_rates_description
+	  { 
+	    Fl_Group.current()->add(dbAction);
+	    dbAction->resize(380, 310, 105, 25);
+	    dbAction->down_box(FL_BORDER_BOX);
+	    dbAction->labeltype(FL_NO_LABEL);
+	    dbAction->labelsize(16);
+	    dbAction->textsize(16);
+	  } // Fl_Choice* dbAction
+	  { 
+	    Fl_Group.current()->add(btnDbAction);
+	    btnDbAction->resize(380, 345, 105, 25);
+	    btnDbAction->label(_tr("Action"));
+	    btnDbAction->labelsize(16);
+	  } // Fl_Button* btnDbAction
+	  editGroup->end();
+	} // Fl_Group* editGroup
+	end();
+}
+function add_input_field_to_map(tbl, fldname, fld){
+	db_map[fldname] <- fld;
+}
+}

+ 1009 - 0
ourbiz/sq-server-plugin.nut

@@ -0,0 +1,1009 @@
+local globals = getroottable();
+if(!globals.get("APP_CODE_FOLDER", false)) ::APP_CODE_FOLDER <- ".";
+
+//local AT_DEV_DBG=true;
+
+//local APP_CODE_FOLDER = sqfs.currentdir();
+//local EDIT_MD5_PASSWORD = md5("edit_user:r.dadbiz.es:okdoedit");
+//local VIEW_MD5_PASSWORD = md5("view_user:r.dadbiz.es:okdoview");
+
+function checkCompaniesUkDBFile(){
+	if (globals.get("jniLog", false)) return APP_CODE_FOLDER + "/companies-uk-RG.db";
+	return "/media/USBHD320/bo/uk/companies-uk-RG.db";
+}
+
+if(!globals.get("gmFile", false)) ::gmFile <- blob();
+if(!globals.get("__tplCache", false)) ::__tplCache <- {};
+if(!globals.get("__stmtCache", false)) ::__stmtCache <- {};
+if(!globals.get("db", false)) ::db <- SQLite3(checkCompaniesUkDBFile());
+::db.exec_dml("PRAGMA cache_size = 4000;");
+	
+function getTemplate(fname, nocache){
+	local mixBase = ::__tplCache.get(fname, false);
+	if (!mixBase || nocache){
+		local rfn = format("%s/%s", APP_CODE_FOLDER, fname);
+//debug_print("\n", rfn);
+		try {
+			mixBase = sqmix.loadfile(rfn);
+		} catch(e){
+			debug_print("\n", e);
+		}
+		::__tplCache[fname] <- mixBase;
+	}		
+	return mixBase;
+}
+
+function getCachedStmt(stmt_key, sql_or_func){
+	local stmt = ::__stmtCache.get(stmt_key, false);
+	if (!stmt){
+		//local db =checkCompaniesUkDB()
+		local sql;
+		if (type(sql_or_func) == "function") sql = sql_or_func();
+		else sql = sql_or_func;
+//debug_print("\n", sql);
+		stmt = ::db.prepare(sql);
+		::__stmtCache.stmt_key <- stmt;
+	}
+	return stmt;
+}
+
+function unescapeHtml ( str ){
+	if (str){
+		return str.gsub("(&[^;]-;)", function(m){
+				if (m == "&lt;") return "<";
+				else if (m == "&gt;") return ">";
+				else if (m == "&amp;") return "&";
+				return m;
+			});
+	}
+}
+
+function escapeHtml ( str ){
+	if (str){
+		return str.gsub("([<>&])", function(m){
+				if (m == "<") return "&lt;";
+				else if (m == ">") return "&gt;";
+				else if (m == "&") return "&amp;";
+				return m;
+			});
+	}
+}
+
+function fillTemplate(template, data, nocache){
+	data.escapeHtml <- escapeHtml;
+	local mixFunc =getTemplate(template, nocache);
+	mixFunc.call(data);
+}
+
+//
+// Post
+//
+function split_filename(path){
+  local result;
+  path.gmatch("[/\\]?([^/\\]+)$", function(m){
+	result = m;
+	return false;
+  });
+  return result;
+}
+
+function insert_field (dest, key, value){
+  local fld = dest.get(key, null);
+  if (!fld) dest[key] <- value;
+  else 
+  {
+	if (type (fld) == "array") fld.push(value);
+	else  dest[key] <- [fld, value];
+  }
+}
+
+function multipart_data_get_field_names(headers, name_value){
+  local disp_header = headers["content-disposition"] || "";
+  local attrs = {};
+  disp_header.gmatch(";%s*([^%s=]+)=\"(.-)\"", function(attr, val) {
+	attrs[attr] <- val;
+	return true;
+  });
+  name_value[0] = attrs.name;
+  name_value[1] = attrs.filename ? split_filename(attrs.filename) : null;
+}
+
+function multipart_data_break_headers(header_data){
+	local headers = {};
+	header_data.gmatch("([^%c%s:]+):%s+([^\n]+)", function(type, val){
+		headers[type.tolower()] <- val;
+		return true;
+	});
+	return headers;
+}
+
+function multipart_data_read_field_headers(input, state){
+	local s, e, pos = state.pos;
+	input.lua_find("\r\n\r\n", function(start, end){s=start; e=end; return false;}, pos, true);
+	if( s ) {
+		state.pos = e+1;
+		return multipart_data_break_headers(input.slice(pos, s-1));
+	}
+	else return nil;
+}
+
+function multipart_data_read_field_contents(input, state){
+	local boundaryline = "\r\n" + state.boundary;
+	local s, e, pos = state.pos;
+	input.find_lua(boundaryline, function(start, end){ s=start; e=end; return false;}, pos, true)
+	if (s) {
+		state.pos = e+1;
+		state.size = s-pos;
+		return input.slice(pos, s-1);
+	}
+	else {
+		state.size = 0;
+		return nil;
+	}
+}
+
+function multipart_data_file_value(file_contents, file_name, file_size, headers){
+  local value = { contents = file_contents, name = file_name, size = file_size };
+  foreach( h, v in headers) {
+	if (h != "content-disposition") value[h] = v;
+  }
+  return value;
+}
+
+function multipart_data_parse_field(input, state){
+	local headers, value;
+	
+	headers = multipart_data_read_field_headers(input, state);
+	if (headers) {
+		local name_value=[];
+		multipart_data_get_field_names(headers, name_value);
+		if (name_value[1]) { //file_name
+			value = multipart_data_read_field_contents(input, state);
+			value = multipart_data_file_value(value, name_value[1], state.size, headers);
+			name_value[1] = value;
+		}
+		else name_value[1] = multipart_data_read_field_contents(input, state)
+		return name_value;
+	}
+	return null;
+}
+
+function multipart_data_get_boundary(content_type){
+	local boundary;
+	content_type.gmatch("boundary%=(.-)$", function(m){
+		boundary = m;
+		return false;
+	});
+	return "--" + boundary;
+}
+
+function parse_multipart_data(input, input_type, tab={}){
+	local state = {};
+	state.boundary <- get_boundary(input_type);
+	input.find_lua(state.boundary, function(start, end){state.pos = end+1;return false;}, 0, true);
+	while(true){
+		local name_value = multipart_data_parse_field(input, state);
+		if(!name_value) break;
+		insert_field(tab, name_value[0], name_value[1]);
+	}
+	return tab;
+}
+
+function parse_qs(qs, tab={}){
+	if (type(qs) == "string") {
+		//debug_print(qs)
+		qs.gmatch("([^&=]+)=([^&=]*)&?", function(key,val){
+			//debug_print(key, "->", val)
+			insert_field(tab, url_decode(key), url_decode(val));
+			return true;
+		});
+	}
+	else if (qs) throw("Request error: invalid query string");
+
+	return tab;
+}
+
+function parse_qs_to_table(qs, tab={}){
+	if (type(qs) == "string") {
+		//debug_print(qs)
+		qs.gmatch("([^&=]+)=([^&=]*)&?", function(key,val){
+			//debug_print(key, "->", val)
+			key = url_decode(key);
+			tab[key] <- url_decode(val);
+			return true;
+		});
+	}
+	else if (qs) throw("Request error: invalid query string");
+
+	return tab;
+}
+
+function parse_qs_to_table_k(qs, tab={}, tabk=[]){
+	if (type(qs) == "string") {
+		qs.gmatch("([^&=]+)=([^&=]*)&?", function(key, val){
+		//debug_print(key, "->", val)
+			key = url_decode(key);
+			tabk.push(key);
+			tab[key] <- url_decode(val);
+			return true;
+		});
+	}
+	else if (qs) throw("Request error: invalid query string");
+	return tab;
+}
+
+function parse_post_data(input_type, data, tab = {}){
+	local length = data.len();
+	if (input_type.find("x-www-form-urlencoded") >= 0) parse_qs(data, tab);
+	else if (input_type.find("multipart/form-data") >= 0) parse_multipart_data(data, input_type, tab);
+	else if (input_type.find("SLE") >= 0) {
+		local vv = sqlite3.sle2vecOfvec(data);
+		if (vv.len() > 0) {
+			local names = vv[0];
+			local values = vv[1];
+			for (local i=0, len = names.len(); i < len; ++i){
+				tab[names[i]] = values[i];
+			}
+		}
+	}  
+	return tab;
+}
+
+function get_post_fields(request, max_len=1024*1000){
+	local data_len = (request.get_header("Content-Length") || "0").tointeger();
+	local post_fields = {};
+	if (data_len > 0 && data_len <= max_len) {
+		local content_type = request.get_header("Content-Type") || "x-www-form-urlencoded";
+		local data = request.read(data_len);
+/*
+		local fd = file("post.txt", "wb");
+		fd.write(data, data.len());
+		fd.close();
+		debug_print(conn_get_header("Content-Type"), "\n");
+*/		
+		parse_post_data(content_type, data, post_fields);
+	}
+	return post_fields;
+}
+
+function sanitizePath(path){
+	//reorient separators
+	path=path.gsub("\\", "/");
+
+	//remove relativeness
+	local relatpattern = "%.%.+";
+
+	while (path.find_lua(relatpattern) > 0){
+		path=path.gsub(relatpattern, "") //something like    /Repositories/swycartographer/res/msys/ + /mod
+	}                              //gets converted to /Repositories/swycartographer/res/msys/mod
+
+	//remove possible doubles
+	relatpattern = "//";
+	while(path.find(relatpattern) >= 0){
+		path=path.gsub(relatpattern, "/");
+	}
+
+	//remove trailing slash
+	if(path.endswith("/")) path=path.slice(0,-2);
+	//remove slash at the begining
+	if(path.startswith("/")) path = path.slice(1);
+	path = path.gsub("[^A-Za-z0-9_%-%./]", "");
+	return path
+}
+
+local allowedEditFileExtensions = {
+	[".nut"] = true,
+	[".tpl"] = true,
+	[".html"] = true,
+	[".css"] = true,
+	[".js"] = true,
+}
+
+function isExtensionAllowed(fname){
+	local ext;
+	fname.gmatch("(%.?[^%.\\/]*)$", @(m) ext=m)
+	if( ext ) return allowedEditFileExtensions.get(ext, false);
+	return false;
+}
+
+function getFilesInPath(path, files=[], prefix=""){
+	foreach( file in sqfs.dir(path) ){
+		if(file != "." && file != ".." ){
+			local f = path + "/" + file;
+			local pf
+			if (prefix.len() > 0) pf = prefix + "/" + file;
+			else pf = file;
+
+			local attr = sqfs.attributes (f);
+			
+			if(attr.mode == "directory") getFilesInPath (f, files, pf);
+			else
+			{
+				if( isExtensionAllowed(pf) ) files.push(pf);
+				//foreach(name, value in attr) print (name, value);
+			}
+		}
+	}
+	files.sort();
+	return files;
+}
+
+function getDbListFromStmt(stmt, maxSeconds=0){
+	local error_code = 0;
+	local rows = [];
+	local db = stmt.get_db();
+	if (maxSeconds){
+		//local x = 0
+		db.progress_handler(25, function(info) {
+			//x = x +1
+			//debug_print(x, "\n")
+			//debug_print(x, ":", os.difftime(os.time(), info[0]), ":", info[1], "\n")
+			if (os.difftime(os.time(), info[1]) > info[0]) return 1;
+			return 0;
+		}, [maxSeconds, os.time()]);
+	}
+	else db.progress_handler(null);
+
+	try {
+		while (stmt.next_row()){
+			rows.push(stmt.asArray());
+		}
+	} catch(e){
+		error_code = db.error_code();
+	}
+	
+	if (maxSeconds) db.progress_handler(null);
+	stmt.reset();
+	//debug_print("\n", rows.len(), "\n");
+	return [rows, error_code];
+}
+
+function strHasContent(v){
+	if(v && v.len() > 0) return true;
+	return false;
+}
+
+function getCiaUkSearchList(search_str, search_post_code, search_sic_code, 
+			search_origin_post_code, search_around_post_code , sic_street, page, limit){
+	local offset = page * limit;
+	local post_code_radius = strHasContent(search_around_post_code) ? search_around_post_code.tointeger() : 0; 
+	local stmt, stmt_count, bind_str;
+	local hasSicSearch = false;
+	local bind_names;
+	local base_sql = "select c.id, c.number, c.name, round((julianday('now') - julianday(incorporation_date)) / 354, 1) as age, c.post_code from companies  c "
+	//debug_print(search_str or "nil", "\t",search_post_code or "nil", "\t", search_sic_code or "nil", "\t", page, "\n")
+	//print(search_str, search_post_code, search_sic_code, search_origin_post_code, search_around_post_code , page, limit)
+	//print("AtLine:", __LINE__)
+	if (strHasContent(search_str) && search_str.find_lua("%d+") == 0){
+		bind_str1 = search_str;
+		limit = 0;
+		stmt = getCachedStmt("getCiaUkSearchList1", @() format(" %s where c.number = ?", base_sql));
+	}
+	else if (post_code_radius > 0 && strHasContent(search_origin_post_code)){
+		local sic_codes_sql = "";
+		local sic_code = null;
+		local cached_stmt_name = "";
+		local radius_sql_base = [==[
+%s, post_codes pc, post_codes ref
+where  ref.post_code = :post_code
+and pc.easting > ref.easting - :radius and pc.easting < ref.easting + :radius
+and pc.northing > ref.northing - :radius and pc.northing < ref.northing +:radius
+and is_inside_circle( ref.easting, ref.northing, :radius, pc.easting, pc.northing)
+and c.post_code = pc.post_code
+%s
+limit :limit offset :offset
+]==];
+		if (strHasContent(search_sic_code)){
+			if (search_sic_code.find_lua("%d+") == 0){
+				sic_codes_sql = "and c.id in(select company_id from companies_sic_codes where sic_code like :sic_code)";
+				sic_code = search_sic_code + "%";
+				cached_stmt_name = "getCiaUkSearchList2";
+			}
+			else
+			{
+				sic_code = search_sic_code;
+				sic_codes_sql = "and c.id in(select company_id from companies_sic_codes csc,  sic_codes_fts sc where sic_codes_fts  match :sic_code and csc.sic_code = sc.docid)";
+				cached_stmt_name = "getCiaUkSearchList3";
+			}
+		}
+
+		//debug_print("\n", string.format(radius_sql_base, base_sql, sic_codes_sql) )
+		stmt = getCachedStmt(cached_stmt_name, @() format(radius_sql_base, base_sql, sic_codes_sql));
+		limit = 50;
+		offset = page * limit;
+		bind_names = {post_code = search_origin_post_code, radius = post_code_radius, limit=limit, offset=offset};
+		if (sic_code) bind_names.sic_code <- sic_code;
+	}
+	else if (strHasContent(search_str) && strHasContent(search_post_code)){
+		stmt = getCachedStmt("getCiaUkSearchList4", @() format([==[
+%s, companies_fts cf
+where companies_fts match ?
+and c.id = cf.docid
+limit ? offset ?
+]==], base_sql));
+		search_post_code = search_post_code.gsub("%s+", "");
+		bind_str = format("name:%s post_code:%s", search_str, search_post_code);
+	}
+	else if (strHasContent(search_post_code)){
+		if (strHasContent(search_sic_code)){
+			hasSicSearch = true;
+			local sic_code_sql;
+			if (search_sic_code.find_lua("%d+") == 0){
+				stmt = getCachedStmt("getCiaUkSearchList5", @() format([==[ 
+%s, companies_sic_codes csc 
+where csc.sic_code like :sic_code
+and c.id = csc.company_id
+and c.post_code like :post_code
+limit :limit offset :offset
+]==], base_sql));
+				bind_names = {post_code = glob2Sql(search_post_code), sic_code = glob2Sql(search_sic_code), limit=limit, offset=offset};
+			}
+			else
+			{
+				stmt = getCachedStmt("getCiaUkSearchList6", @() format([==[ 
+%s , companies_sic_codes csc , sic_codes_fts sc
+where sic_codes_fts match :sic_code
+and csc.sic_code = sc.docid
+and c.id = csc.company_id
+and c.post_code like :post_code
+limit :limit offset :offset
+]==], base_sql));
+				bind_names = {post_code = glob2Sql(search_post_code), sic_code = search_sic_code, limit=limit, offset=offset};
+			}
+		}
+		else
+		{
+			stmt = getCachedStmt("getCiaUkSearchList7", @() format([==[ 
+%s, companies_fts cf
+where companies_fts match ?
+and c.id = cf.docid
+limit ? offset ?
+]==], base_sql));
+		}
+		search_post_code = search_post_code.gsub("%s+", "_");
+		bind_str = format("post_code:%s*", search_post_code);
+	}
+	else if ( (!strHasContent(search_str)) && (!strHasContent(search_post_code)) && strHasContent(search_sic_code)) {
+		if (sic_street && sic_street == "street"){
+			search_sic_code = "%" + search_sic_code + "%";
+			stmt = getCachedStmt("getCiaUkSearchList8", "select distinct id, address, post_code from companies where address like ? order by 2 limit ? offset ?");
+		}
+		else if (search_sic_code.find_lua("%d+") == 0){
+			search_sic_code = search_sic_code + "%";
+			stmt = getCachedStmt("getCiaUkSearchList9", "select * from sic_codes where id like ? limit ? offset ?");
+		}
+		else
+		{
+			stmt = getCachedStmt("getCiaUkSearchList10", "select sc.* from sic_codes sc, sic_codes_fts scf where sic_codes_fts match ?  and sc.id = scf.docid limit ? offset ?");
+		}
+		bind_str = search_sic_code;
+	}
+	else
+	{
+		bind_str = search_str;
+		stmt = getCachedStmt("getCiaUkSearchList11", @() format([==[ 
+%s, companies_fts cf
+where cf.name match ?
+and c.id = cf.docid
+limit ? offset ?
+]==], base_sql));
+	}
+	
+	local xp = 1;
+	stmt.reset();
+//debug_print("\n", bind_str, ":", limit, ":", offset);
+	if (bind_names) stmt.bind_names(bind_names);
+	else
+	{
+		stmt.bind(xp++, bind_str);
+		if (hasSicSearch) stmt.bind(xp++, search_sic_code);
+
+		if (limit > 0) {
+			stmt.bind(xp++, limit);
+			stmt.bind(xp++, offset);
+		}
+	}
+	local result = getDbListFromStmt(stmt, 30);
+	result.push(limit);
+	return  result;
+}
+
+function getOneDbNamedValuesFromStmt(stmt){
+	local result;
+	if (stmt.step() == stmt.SQLITE_ROW) result = stmt.asTable();
+	stmt.reset();
+	return result || {};
+}
+
+function getCiaUkById(id){
+	local stmt = getCachedStmt("getCiaUkById", "select * from company_view where id = ?");
+	stmt.reset();
+	stmt.bind(1, id);
+	return getOneDbNamedValuesFromStmt(stmt);
+}
+
+function getCiaUkByIdSicCodes(id){
+	local stmt = getCachedStmt("getCiaUkByIdSicCodes", "select sc.* from companies_sic_codes csc join sic_codes sc on csc.sic_code = sc.id where company_id = ?");	stmt.reset();
+	stmt.bind(1, id);
+	return getDbListFromStmt(stmt);
+}
+
+function getCiaUkByIdOldNames(id){
+	local stmt = getCachedStmt("getCiaUkByIdOldNames", "select condate, prev_name from companies_old_names where company_id = ?");
+	stmt.reset();
+	stmt.bind(1, id);
+	return getDbListFromStmt(stmt);
+}
+
+function getDistances(search_origin_post_code, rows){
+	if (rows.len() > 0){
+		local stmt = getCachedStmt("getDistances", [==[
+select 
+	round(distance(ref.easting, ref.northing, pc.easting, pc.northing)), 
+	ifnull(round(bearing(ref.easting, ref.northing, pc.easting, pc.northing)), 0)
+from companies c left join post_codes pc on c.post_code = pc.post_code,
+	post_codes ref
+where c.id = ?
+and ref.post_code = ?
+]==]);
+		foreach( k,v in rows) {
+			stmt.reset();
+			stmt.bind(1, v[0]);
+			stmt.bind(2, search_origin_post_code);
+			if (stmt.step() == stmt.SQLITE_ROW){
+				v.push(stmt.col(0));
+				v.push(stmt.col(1));
+			}
+		}
+		//stmt.reset();
+		stmt.finalize();
+		rows.sort(@(a,b) (a[6] || 0) <=> (b[6] || 0));
+	}
+}
+
+function getEastinNorthingForPostCode(post_code){
+	local stmt = getCachedStmt("getEastinNorthingForPostCode", [=[
+select easting, northing
+from post_codes
+where post_code = ?
+]=]);
+	stmt.bind(1, post_code);
+	local easting, northing;
+	if (stmt.step() == stmt.SQLITE_ROW){
+		easting = stmt.col(0);
+		northing = stmt.col(1);
+	}
+	stmt.finalize();
+	return [easting, northing];
+}
+
+function toDeg(lat){
+    return lat * 180.0 / math.PI;
+}
+
+ function toRad(x) {
+	return x * math.PI / 180.0;
+ }
+
+//
+// Convert Ordnance Survey grid reference easting/northing coordinate to (OSGB36) latitude/longitude
+//
+// @param {OsGridRef} easting/northing to be converted to latitude/longitude
+// @return {LatLon} latitude/longitude (in OSGB36) of supplied grid reference
+//
+function osGridToLatLong(easting, northing){
+  local E = easting.tofloat();
+  local N = northing.tofloat();
+
+  local sin = math.sin;
+  local cos = math.cos
+  local PI = math.PI;
+  local a = 6377563.396;
+  local b = 6356256.910;              // Airy 1830 major & minor semi-axes
+  local F0 = 0.9996012717;                             // NatGrid scale factor on central meridian
+  local lat0 = 49.0*PI/180.0;
+  local lon0 = -2.0*PI/180.0;  // NatGrid true origin
+  local N0 = -100000.0;
+  local E0 = 400000.0;                     // northing & easting of true origin, metres
+  local e2 = 1.0 - (b*b)/(a*a);                          // eccentricity squared
+  local n = (a-b)/(a+b);
+  local n2 = n*n;
+  local n3 = n*n*n;
+
+  local lat=lat0;
+  local M=0.0;
+  do {
+    lat = (N-N0-M)/(a*F0) + lat;
+
+    local Ma = (1.0 + n + (5.0/4.0)*n2 + (5.0/4.0)*n3) * (lat-lat0);
+    local Mb = (3.0*n + 3.0*n*n + (21.0/8.0)*n3) * sin(lat-lat0) * cos(lat+lat0);
+    local Mc = ((15.0/8.0)*n2 + (15.0/8.0)*n3) * sin(2*(lat-lat0)) * cos(2*(lat+lat0));
+    local Md = (35.0/24.0)*n3 * sin(3.0*(lat-lat0)) * cos(3*(lat+lat0));
+    M = b * F0 * (Ma - Mb + Mc - Md);                // meridional arc
+
+  } while (N-N0-M >= 0.00001);  // ie until < 0.01mm
+
+  local cosLat = cos(lat);
+  local sinLat = sin(lat);
+  local nu = a*F0/math.sqrt(1.0-e2*sinLat*sinLat);              // transverse radius of curvature
+  local rho = a*F0*(1.0-e2)/math.pow(1.0-e2*sinLat*sinLat, 1.5);  // meridional radius of curvature
+  local eta2 = nu/rho-1.0;
+
+  local tanLat = math.tan(lat);
+  local tan2lat = tanLat*tanLat;
+  local tan4lat = tan2lat*tan2lat;
+  local tan6lat = tan4lat*tan2lat;
+  local secLat = 1.0/cosLat;
+  local nu3 = nu*nu*nu;
+  local nu5 = nu3*nu*nu;
+  local nu7 = nu5*nu*nu;
+  local VII = tanLat/(2.0*rho*nu);
+  local VIII = tanLat/(24.0*rho*nu3)*(5+3.0*tan2lat+eta2-9.0*tan2lat*eta2);
+  local IX = tanLat/(720.0*rho*nu5)*(61+90.0*tan2lat+45.0*tan4lat);
+  local X = secLat/nu;
+  local XI = secLat/(6.0*nu3)*(nu/rho+2.0*tan2lat);
+  local XII = secLat/(120.0*nu5)*(5+28.0*tan2lat+24.0*tan4lat);
+  local XIIA = secLat/(5040.0*nu7)*(61+662.0*tan2lat+1320.0*tan4lat+720.0*tan6lat);
+
+  local dE = (E-E0);
+  local dE2 = dE*dE;
+  local dE3 = dE2*dE;
+  local dE4 = dE2*dE2;
+  local dE5 = dE3*dE2;
+  local dE6 = dE4*dE2;
+  local dE7 = dE5*dE2;
+  
+  lat = lat - VII*dE2 + VIII*dE4 - IX*dE6;
+  local lon = lon0 + X*dE - XI*dE3 + XII*dE5 - XIIA*dE7;
+  
+  return [toDeg(lat), toDeg(lon)];
+  //return lat, lon
+}
+
+function osGridToLatLongAdjusted(easting, northing){
+	local lat_long = osGridToLatLong(easting, northing)
+	//adjust lat, lon 
+	lat_long[0] += 0.0024;
+	lat_long[1] -=  0.00145;
+	return lat_long;
+}
+
+function getLatitudeLongitudeForPostCode(post_code){
+	local easting_northing = getEastinNorthingForPostCode(post_code);
+	return osGridToLatLongAdjusted(easting_northing[0], easting_northing[1]);
+}
+
+function downloadChunked(host, file, extra_header=null){
+	local sock = socket.tcp();
+	sock.settimeout(1000);
+	sock.connect(host, 80);
+
+	local count = 0;    // counts number of bytes read
+	local req;
+	if (extra_header) req = extra_header;
+	else req = format("GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", file, host);
+	
+	//print("REQUEST:", req)
+	sock.send(req);
+	local s;
+	local data = [];
+	while (true){
+		local rc = sock.receive("*a");
+		if(rc[1] == socket.IO_CLOSED) break;
+		else if(rc[1] != socket.IO_DONE) throw (format("socket io error (%d)", rc[1]));
+		s = rc[0];
+		if (s.len() == 0){
+			break;
+		}
+		data.push(s);
+	}
+	sock.close();
+	//print(file, count)
+	return data.concat("\n");
+}
+
+function getExtraCompanyDataOnNet(cnum){
+	local mainHost = "wck2.companieshouse.gov.uk";
+
+	//get session
+	local page;
+	try {
+		page = downloadChunked(mainHost, "/");
+	} catch(e){
+	}
+	if (!page) return "";
+	
+	local cookie1, cookie2;
+	local function getCookie(){
+		page.gmatch("Set%-Cookie: (chcookie=[^;]+)", function(m){ cookie1=m; return false});
+		page.gmatch("Set%-Cookie: (ch_session=[^;]+)", function(m){ cookie2 = m; return false});
+		return cookie1 + ", " + cookie2;
+	}
+	local location;
+	page.gmatch("Location: http://wck2.companieshouse.gov.uk(.-)wcframe", function(m) {location=m; return false;});
+	
+	//print("LOCATION:", getCookie(), location, page)
+
+	//http://wck2.companieshouse.gov.uk/466fc35f66bf9ef61decbe1581a24080/companysearch
+
+	local postBody = format("cname=&cnumb=%s&stype=A&live=on&cosearch.x=30&cosearch.y=9&cosearch=1", cnum);
+
+	local extra_header = format([==[
+POST %scompanysearch HTTP/1.1
+Host: %s
+Cookie: %s
+Content-Type:application/x-www-form-urlencoded
+Content-Length:%d
+Origin:http://wck2.companieshouse.gov.uk
+Referer:http://wck2.companieshouse.gov.uk//wcframe?name=accessCompanyInfo
+User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11
+
+%s
+]==], location, mainHost, getCookie(), postBody.len(), postBody);
+
+	try {
+		page = downloadChunked(mainHost, "/", extra_header);
+	} catch(e){
+		if(e != "closed") throw e;
+	}
+
+	extra_header = format([==[
+GET %swcprodorder?ft=1 HTTP/1.1
+Host: %s
+Cookie: %s
+Host:wck2.companieshouse.gov.uk
+Referer:http://wck2.companieshouse.gov.uk//wcframe?name=accessCompanyInfo
+User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11
+
+]==], location, mainHost, getCookie());
+
+	//print(extra_header)
+
+	page = null;
+	try {
+		page = downloadChunked(mainHost, "/", extra_header);
+	} catch(e){
+		if(e != "closed") throw e;
+	}
+	if (!page) return "";
+
+	//print(err, page)
+
+	local tdata = [];
+	local data;
+	page.gmatch([==[<!%-%- HTML For any but last document %-%->(.-)<table width="90%%" border="0" cellspacing="0" cellpadding="0" summary="Table order button">]==],
+		function(m){data = m; return false;});
+	if (!data) return "";
+
+	data.gmatch([==[<!%-%- FILE_END::.-tmpl %-%->.-<td align="left" class="text">(.-)</td>.-<td align="left"><span class="text">(.-)</span>.-<td class="text">(.-)</td>]==],
+		function(vtype, vdate, vdesc){ tdata.push(format("%s|%s|%s", vtype, vdate, vdesc)); return true;}); 
+
+	data = tdata.concat("\n");
+	data = data.gsub("<[^>]->", "");
+	data = data.replace("&nbsp;", "");
+	data = data.replace("&amp;", "&");
+	data = data.replace("&#39;", "'");
+	return data;
+}
+
+function getExtraCompanyData(cid, cnum){
+	local data;
+	local stmt = ::db.prepare("select data from company_extra_data where id = ?");
+	stmt.reset();
+	stmt.bind(1, cid);
+	
+	if (stmt.step() == stmt.SQLITE_ROW){
+		data = stmt.col(0);
+	}
+	stmt.reset();
+	if(data) return data;
+
+	try {
+		data = getExtraCompanyDataOnNet(cnum);
+		local stmt2 = ::db.prepare("insert into company_extra_data(id, data) values(?,?)");
+		stmt2.reset();
+		stmt2.bind(1, cid);
+		stmt2.bind(2, data);
+		stmt2.step();
+		//debug_print("company_extra_data", checkCompaniesUkDB():error_message())
+		stmt2.reset();
+		return data;
+	} catch(e){
+		return "";
+	}
+}
+
+dofile(APP_CODE_FOLDER + "/ourbiz.nut");
+
+local uri_handlers = {
+	["/SQ/testParams"] = function(request){
+		request.print("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n")
+		request.print("<html><body><h1>Request Info</h1><ul>")
+		foreach(k, v in request.info) {
+			if ("table" == type(v) ){
+				request.print(format("<li><b>%s</b>:</li><ul>", k));
+				foreach( k2, v2 in v){
+					request.print(format("<li><b>%s</b>: %s</li>", k2, v2));
+				}
+				request.print("</ul>");
+			}
+			else request.print(format("<li><b>%s</b>: %s</li>", k, (v == NULL ? "" : v).tostring()));
+		}
+		request.print("</ul></body></html>");
+		return true;
+	},	
+	["/SQ/logout"] = function(request){
+		request.close_session();
+		request.print(format("HTTP/1.1 302 Found\r\nLocation: http://%s\r\n\r\n", request.info.http_headers.Host))
+		return true;
+	},
+	["/SQ/edit"] = function(request){
+		//password protected
+		bool_t canEdit = false;
+		//print("EDIT_MD5_PASSWORD=", EDIT_MD5_PASSWORD, "\n")
+		bool_t isViewOnly = VIEW_MD5_PASSWORD && request.check_password(VIEW_MD5_PASSWORD);
+		if (!isViewOnly) canEdit = EDIT_MD5_PASSWORD && request.check_password(EDIT_MD5_PASSWORD);
+	
+		if(!(canEdit || isViewOnly) ) {
+			request.send_authorization_request("r.dadbiz.es");
+			return true;
+		}
+		 
+		table_t data = {
+			file_name=null,
+			content=null,
+		};
+		data.files <- getFilesInPath(APP_CODE_FOLDER);
+		local query_string = request.info.query_string;
+		bool_t isPost = request.info.request_method == "POST";
+		if (isPost && canEdit) {
+			local post_fields = get_post_fields(request);
+			if (post_fields.get("save", false)) {
+				local content = post_fields.get("content", null);
+				if (content){
+					data.file_name <- sanitizePath(post_fields.file_name);
+					if (!isExtensionAllowed(data.file_name)) data.file_name = NULL;
+					else
+					{
+						local fd = file(APP_CODE_FOLDER + "/" + data.file_name, "w");
+						content = content.gsub("\r", "");
+						fd.write(content);
+						fd.close();
+					}
+				}
+			}
+		}
+		else if( query_string ) data.file_name <- request.get_var(query_string, "file");
+		
+		//debug_print(data.search_id, "\n")
+		if( data.file_name ){
+			data.file_name = sanitizePath(data.file_name);
+			if(! isExtensionAllowed(data.file_name) ) data.file_name = NULL;
+			else
+			{
+				local fd = file(APP_CODE_FOLDER + "/" + data.file_name, "r");
+				if( fd ){
+					data.content <- fd.read(fd.len());
+					fd.close();
+				}
+			}
+		}
+				
+		//debug_tprint(data.company)
+		
+		local mFile = gmFile;
+		mFile.clear(); //allways reset global vars
+		data.mix_write <- function(str){ mFile.write(str || "")}
+		fillTemplate("webappedit.tpl", data, AT_DEV_DBG);
+		request.print(format("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %d\r\n\r\n", mFile.len()));
+		request.write_blob(mFile);
+		return true;
+	},
+	["/search"] = function(request){
+		table_t data = {};
+		data.page_name <- "search_results"
+		data.limit <- 25;
+		local query_string = request.info.query_string;
+		bool_t isPost = request.info.request_method == "POST";
+		local filed_names = ["search_str", "search_post_code", "search_origin_post_code", 
+			"search_around_post_code", "search_sic_code", "sic_street", "page"];
+		if (isPost) {
+			local post_fields =  get_post_fields(request);
+			foreach(k in filed_names) data[k] <- post_fields.get(k, null);
+		}
+		else if (query_string) {
+			foreach(k in filed_names) data[k] <-request.get_var(query_string, k);
+		}
+		else foreach(k in filed_names) data[k] <- null;
+		if(!data.get("page", null))  data.page <- 0;
+		else data.page = data.page.tointeger();
+		
+		local errcode;
+		if (strHasContent(data.search_str) || strHasContent(data.search_post_code) || strHasContent(data.search_sic_code)) {
+			data.sicSearchResults <- strHasContent(data.search_sic_code) && !(strHasContent(data.search_str) || strHasContent(data.search_post_code))
+			local result = getCiaUkSearchList(data.search_str, data.search_post_code, data.search_sic_code, 
+				data.search_origin_post_code, data.search_around_post_code , data.sic_street, data.page, data.limit);
+				
+			if (result[1] /*errcode*/ == SQLite3.SQLITE_INTERRUPT) {
+				data.queryWasInterrupted <- true;
+			}
+			data.rows <- result[0];
+			data.limit <- result[2];
+			if (!data.sicSearchResults && data.rows.len() == 1) {
+					request.print(format("HTTP/1.1 302 Found\r\nLocation: /view?id=%d\r\n\r\n", data.rows[0][0]));
+					return true;			
+			}
+			if (strHasContent(data.search_origin_post_code)) {
+				getDistances(data.search_origin_post_code, data.rows);
+			}
+		}
+		
+		local mFile = gmFile;
+		mFile.clear();
+		data.mix_write <- function(str) {if(str) mFile.write(str);}
+		fillTemplate("index.tpl", data, AT_DEV_DBG);
+		request.print(format("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %d\r\n\r\n", mFile.len()));
+		request.write_blob(gmFile);
+		return true;
+	},
+	["/view"] = function(request){
+		local data = {};
+		data.page_name <- "view_company";
+		local query_string = request.info.query_string;
+		if (query_string) data.search_id <- request.get_var(query_string, "id");
+
+		//debug_print(data.search_id, "\n")
+		if (strHasContent(data.search_id)){
+			data.company <- getCiaUkById(data.search_id);
+			local result = getCiaUkByIdSicCodes(data.search_id);
+			data.company_sic_codes <- result[0];
+			result = getCiaUkByIdOldNames(data.search_id);
+			data.company_old_names <- result[0];
+			data.extra_data <- getExtraCompanyData(data.company.id, data.company.number);
+			if (data.company.post_code) {
+				local lat_long = getLatitudeLongitudeForPostCode(data.company.post_code);
+				data.latitude <- lat_long[0];
+				data.longitude <- lat_long[1];
+			}
+		}
+		local filed_names = ["search_str", "search_post_code", "search_origin_post_code", 
+			"search_around_post_code", "search_sic_code", "sic_street", "page"];
+		foreach(k in filed_names) data[k] <- null;
+		
+		//debug_tprint(data.company)
+		
+		local mFile = gmFile;
+		mFile.clear();
+		data.mix_write <- function(str) {mFile.write(str || "");}
+		fillTemplate("index.tpl", data, AT_DEV_DBG);
+		request.print(format("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %d\r\n\r\n", mFile.len()));
+		request.write_blob(mFile);
+		return true;
+	},
+	["/OURBIZ"] =function(request){
+		request.print("HTTP/1.1 200 OK\r\nServer: OurBiz\r\nContent-Length: 0\r\n\r\n");
+		return true;
+	},
+	["/DB/GetList"] = ourbizDbGetList,
+	["/DB/GetOne"] = ourbizDbGetOne,
+	["/DB/Action"] = ourbizDbAction,
+	["/DB/GetBin"] = ourbizDbGetBin,
+	["/DB/m"] = ourbizDbMobile,
+}
+
+local ourbiz_password = md5("mingote:ourbiz.dadbiz.es:tr14pink");
+function handle_request(request){
+	//static content served by mongoose directly
+	local request_uri = request.info.uri;
+	//debug_print(request.get_option("document_root"), request_uri, "\n")
+	if(request_uri.startswith("/DB/")){
+		if(!request.check_password(ourbiz_password)) {
+			request.send_authorization_request("ourbiz.dadbiz.es");
+			return true;
+		}
+	}
+	if (request_uri.endswith(".js") || request_uri.endswith(".css") ) return false;
+	if (request_uri == "/index.html" || request_uri == "/" ) return uri_handlers["/search"](request);
+	if( uri_handlers.get(request_uri, false) ) return uri_handlers[request_uri](request);
+	return false;
+}

+ 109 - 0
ourbiz/sq-server.nut

@@ -0,0 +1,109 @@
+local globals = getroottable();
+if(!globals.get("APP_CODE_FOLDER", false)) ::APP_CODE_FOLDER <- ".";
+
+/*
+local _old_import = import;
+::__imported_files <-  {};
+::import = function(fn){
+}
+*/
+
+AT_DEV_DBG <- true;
+
+function getUserCallbackSetup(fn){
+	local fd = file(APP_CODE_FOLDER + "/" + fn, "r");
+	local code = fd.read(fd.len());
+	fd.close();
+	local extra_code = format("APP_CODE_FOLDER <- \"%s\";\n", APP_CODE_FOLDER);
+	
+	if (globals.get("VIEW_MD5_PASSWORD", false)){
+		extra_code += format("VIEW_MD5_PASSWORD <- \"%s\";\n", VIEW_MD5_PASSWORD);
+	} else extra_code += "VIEW_MD5_PASSWORD <- nul;\n";
+	
+	if (globals.get("EDIT_MD5_PASSWORD", false)){
+		extra_code += format("EDIT_MD5_PASSWORD <- \"%s\";\n", EDIT_MD5_PASSWORD);
+	} else extra_code += "EDIT_MD5_PASSWORD <- null;\n";
+	
+	if (globals.get("AT_DEV_DBG", false)){
+		extra_code += "AT_DEV_DBG <- true;\n"
+	} else extra_code += "AT_DEV_DBG <- false;\n"
+	
+	return compilestring(format("%s\n%s", extra_code, code));
+}
+
+local mongoose_start_params = {
+	error_log_file = "sq-mongoose.log",
+	listening_ports = "8080",
+	document_root = "./s",
+	//num_threads = 5,
+
+	//cgi_extensions = "lua",
+	//cgi_interpreter = "/usr/bin/lua",
+	//cgi_interpreter = "C:\\Lua\\5.1\\lua.exe",
+	ssl_certificate = "axTLS.x509_512.pem",
+        //"ssl_certificate", "axTLS.x509_1024.pem",
+        ssl_chain_file = "axTLS_x509_512.cer",
+	extra_mime_types = ".xsl=application/xml",
+	master_plugin = function(){
+		debug_print("done master_plugin\n");
+	},
+	master_plugin_exit = function(){
+		debug_print("done master_plugin_exit\n");
+	},
+	//functions to be used by each independent lua vm
+	user_callback_setup = getUserCallbackSetup("sq-server-plugin.nut"),
+	user_callback_exit = function(){
+		debug_print("done user_callback_exit\n");
+	},
+	user_callback = function(event, request){
+		if(event == "MG_NEW_REQUEST"){
+			if(AT_DEV_DBG || !this.get("handle_request", false)) {
+				loadfile(APP_CODE_FOLDER + "/sq-server-plugin.nut")();
+			}
+			return handle_request(request);
+		}
+		else if(event == "MG_EVENT_LOG"){
+			//debug_print("\n", request.info.log_message);
+			//return true;
+			return false;
+		}
+		else if(event == "MG_HTTP_ERROR" 
+			|| event == "MG_INIT_SSL"){
+				return false;
+		}
+	},
+}
+
+local mg;
+
+function appServerStart(port, document_root){
+	mg = Mongoose();
+	//mongoose_start_params.num_threads <- "2";
+	mongoose_start_params.listening_ports = port;
+	mongoose_start_params.document_root = document_root;
+	mg.show_errors_on_stdout(true);
+	mg.start(mongoose_start_params);
+}
+
+//appServerStart(8087, "./s");
+//stdin.readn('c');
+
+function appServerStop(){
+	if(mg) {
+		mg.stop();
+		mg = null;
+	}
+}
+
+//print( lfs.currentdir())
+
+//
+// myio = io.open("luadump.txt", "wb")
+// myio:write(string.dump(start_params.user_callback))
+// myio:close()
+
+// run until the user presses enter
+//io.read()
+
+//appServerStop()
+

+ 96 - 0
ourbiz/utils-fltk.nut

@@ -0,0 +1,96 @@
+function setAppFont(fontName)
+{
+    local my_font, numfonts, font1, font2;
+ 
+    numfonts=Fl.set_fonts();
+ 
+    for(local i=0; i < numfonts; ++i)
+    {
+        my_font=Fl.get_font(i); // get the name of the current font
+        if( my_font )
+        {
+            local font = Fl.get_font_name(i);
+            //print(my_font_name, my_font_attr)
+            if( font.name )
+            {
+                if( font.name.find(fontName) )
+                {
+                    if( font.attributes != 0 )
+                    {
+                        if (( font.attributes & FL_BOLD) &&
+                                ( font.attributes & FL_ITALIC))
+                        {
+                            font1 = FL_HELVETICA_BOLD_ITALIC;
+                            font2 = FL_TIMES_BOLD_ITALIC;
+                        }
+                        else if(  font.attributes & FL_BOLD )
+                        {
+                            font1 = FL_HELVETICA_BOLD;
+                            font2 = FL_TIMES_BOLD;
+                        }
+                        else if(  font.attributes & FL_ITALIC )
+                        {
+                            font1 = FL_HELVETICA_ITALIC;
+                            font2 = FL_TIMES_ITALIC;
+                        }
+                    }
+                    else
+                    {
+                        font1 = FL_HELVETICA;
+                        font2 = FL_TIMES;
+                    }
+                    //print(bit.band(my_font_attr, FL_BOLD), my_font_attr, font1, font2)
+                    Fl.set_font(font1, i);
+                    Fl.set_font(font2, i);
+                    //break
+                }
+            }
+        }
+    }
+}
+
+function widget_focus_changing_Match(widget){
+	if (widget){
+		local ttype = widget.classId();
+		//print(ttype);
+		if (ttype.find("_Input")) return 1;
+		if (ttype.find("_Browser")) return 2;
+		if (ttype.find("_Tree")) return false;
+		if (ttype.find("_Editor")) return 3;
+		local parent = widget.parent();
+		if (parent && parent.classId().find("_Choice")){
+			return 3;
+		}
+	}
+	return false;
+}
+		
+function fltk_focus_changing(wfrom, wto){
+	//print(wfrom.classId(), wto.classId());
+	//print(wfrom, wto);
+	
+	if (widget_focus_changing_Match(wfrom)){
+		wfrom.color(FL_WHITE);
+		wfrom.redraw();
+	}
+	local wt = widget_focus_changing_Match(wto);
+	if (wt) {
+		wto.color(FL_YELLOW);
+		wto.redraw();
+		//if (wt == 1) wto.position(0,10000);
+	}
+	
+	return 0;
+}
+
+math.number_format_set_dec_point(",");
+math.number_format_set_thousand_sep(".");
+Fl_Input.default_number_format("\0x02,.");
+//Fl:scheme("plastic");
+Fl.scheme("gtk+");
+//use partial match to find verdana font
+Fl.visual(FL_RGB);
+//allow arrow keys navigation
+Fl.option(Fl.OPTION_ARROW_FOCUS, true);
+setAppFont("erdana");
+Fl.add_focus_changing_handler(fltk_focus_changing);

+ 85 - 0
ourbiz/webappedit.tpl

@@ -0,0 +1,85 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>SquiLuWebAppServer</title>
+<link rel="stylesheet" href="/codemirror.css">
+<script src="/codemirror-compressed.js"></script>
+<link rel="stylesheet" href="/dialogs.css">
+<link rel="stylesheet" href="/neat.css">
+<link rel="stylesheet" href="/docs.css">
+<style type="text/css">
+.CodeMirror {border: 1px solid #ccc;}
+#editTable {
+}
+table, th, td
+{
+	border: 1px solid #ccc;
+}
+#editTable td {
+	vertical-align:top;
+}
+#filesCell {
+}
+#editCell {
+	width:80%;
+}
+#editCell textarea {
+	width:100%;
+	height: 30em;
+}
+</style>
+</head>
+<body>
+<h3>SquiLu Web App Server</h3>
+<form method="post">
+<table id="editTable">
+<tr><td id="filesCell">
+<h4>Files</h4>
+<ol>
+<? foreach( k,v in files) { ?>
+  <li><a href="?file=<?=v?>"><?=v?></a></li>
+<? } ?>
+</ol>
+</td><td id="editCell">
+<input type="submit" name="save" value="Save">
+<!--<input type="submit" name="reload" value="Reload">-->
+<input type="text" name="file_name" value="<?=file_name?>">
+<button type="button" onclick="window.location.href='/SQ/logout';">Logout</button>
+  <a href="/" target="myweb">View Page</a>
+<br>
+<textarea name="content" id="code"><?=escapeHtml(content)?></textarea>
+<?
+	function getMode(){
+		if (!file_name) return "xml";
+		local ext;
+		file_name.gmatch("([^.]+)$", function(m) {ext=m; return false;});
+		if (ext == "css")  return "css";
+		else if (ext == "js") return "javascript";
+		else if (ext == "nut") return "javascript";
+		else if (ext == "tpl") return "application/x-ejs";
+		else if (ext == "html") return "text/html";
+		return "xml";
+	}
+?>
+<p><input type="text" value="<?=getMode()?>" id="mode"> 
+  <button type="button" onclick="change()">change mode</button></p>
+</td></tr>
+</table>
+</form>
+<script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
+        tabMode: "indent",
+        matchBrackets: true,
+        lineNumbers: true,
+    	mode: "<?=getMode()?>"
+      });
+var modeInput = document.getElementById("mode");
+CodeMirror.connect(modeInput, "keypress", function(e) {
+  if (e.keyCode == 13) change();
+});
+function change() {
+   editor.setOption("mode", modeInput.value);
+}
+</script>
+</body>
+</html>