"_correspondenceContact": "Correspondence Contact",
"_countries": "Countries",
"_created": "Created",
+ "_createBaseCurr": "Create new Base Currency",
"_createdBy": "Created By",
"_credit": "Credit",
"_creditCard": "Credit Card",
"_primaryContact": "Primary Contact",
"_primaryEmail": "Primary Email",
"_printed": "Printed",
+ "_printOnSave": "Print on Save",
"_priority": "Priority",
"_priorities": "Priorities",
"_privilege": "Privilege",
"_sessionTimedOut": "Your session has timed out",
"_settings": "Settings",
"_setup": "Setup",
+ "_setBaseCurrToUSD": "Set Base Currency to USD ($)",
"_severity": "Severity",
"_shared": "Shared",
"_shift": "Shift",
"_recalculateAll?": "Do you want to recalculate all prices line items, taxes, and freight ?",
"_rescheduleAll": "Changing this date will update the Schedule Date on all " +
"editable line items.",
+ "_selectBaseCurrency": "Please select a base currency for this database:",
"_updateFractional": "The quantity ordered and unit of measure selected will result in a " +
"fractional inventory qty for this item. This item does not allow fractional quantities; " +
"the quantity will be updated accordingly.",
baseCurrency: function () {
if (baseCurr) { return baseCurr; }
- baseCurr = _.find(XM.currencies.models, function (curr) {
+ baseCurr = XM.currencies ? _.find(XM.currencies.models, function (curr) {
return curr.get('isBase');
- });
+ }) : false;
+
return baseCurr;
},
isBase: false
},
+ readOnlyAttributes: [
+ "isBase",
+ ],
+
+ handlers: {
+ "status:READY_CLEAN": "statusReadyClean"
+ },
+
// ..........................................................
// METHODS
//
}
},
+ statusReadyClean: function () {
+ // If there is no Base currency set, make it not readOnly
+ var coll = this.collection,
+ hasBase;
+
+ if (coll && coll.models) {
+ hasBase = _.find(coll.models, function (model) {
+ return model.get("isBase") === true;
+ });
+ }
+
+ this.setReadOnly("isBase", hasBase);
+ },
+
/**
* Converts this currency to another via the base currency. The
* options.success callback is NOT optional.
numberPolicySetting: 'CONumberGeneration',
+ printOnSaveSetting: 'DefaultPrintSOOnSave',
+
documentDateKey: "orderDate",
handlers: {
query: {orderBy: [
{attribute: 'number'}
]},
- allowPrint: true,
parameterWidget: "XV.AccountListParameters",
components: [
{kind: "XV.ListItem", components: [
{attribute: 'name'},
{attribute: 'uuid'}
]},
- allowPrint: true,
multiSelect: true,
components: [
{kind: "XV.ListItem", components: [
{attribute: 'firstName'},
{attribute: 'primaryEmail'}
]},
- allowPrint: true,
parameterWidget: "XV.ContactListParameters",
components: [
{kind: "XV.ListItem", components: [
query: {orderBy: [
{attribute: 'number'}
]},
- allowPrint: true,
multiSelect: true,
parameterWidget: "XV.CustomerListParameters",
components: [
{attribute: 'updated', descending: true},
{attribute: 'number', descending: true, numeric: true}
]},
- allowPrint: true,
toggleSelected: false,
parameterWidget: "XV.IncidentListParameters",
components: [
name: "XV.InvoiceList",
kind: "XV.List",
multiSelect: true,
- allowPrint: true,
label: "_invoices".loc(),
parameterWidget: "XV.InvoiceListParameters",
collection: "XM.InvoiceListItemCollection",
{name: "post", privilege: "PostMiscInvoices", prerequisite: "canPost",
method: "doPost" },
{name: "print", privilege: "PrintInvoices", method: "doPrint", isViewMethod: true },
+ {name: "email", privilege: "PrintInvoices", method: "doEmail", isViewMethod: true},
{name: "download", privilege: "PrintInvoices", method: "doDownload",
- isViewMethod: true }
+ isViewMethod: true}
],
components: [
{kind: "XV.ListItem", components: [
]}
]}
],
- create: function () {
- if (XT.session.config.emailAvailable) {
- this.actions.push({name: "email", method: "doEmail" });
- }
- this.inherited(arguments);
- },
- doPrint: function (options) {
- if (XT.session.config.printAvailable) {
- // send it to be printed silently by the server
- options.model.doPrint();
- } else {
- // no print server set up: just pop open a tab
- window.open(XT.getOrganizationPath() + options.model.getReportUrl(),
- "_newtab");
- }
- },
- doDownload: function (options) {
- window.open(XT.getOrganizationPath() + options.model.getReportUrl("download"),
- "_newtab");
- },
// some extensions may override this function (i.e. inventory)
formatAddress: function (value, view, model) {
var city = model.get("billtoCity"),
{attribute: 'name'},
{attribute: 'number', numeric: true}
]},
- allowPrint: true,
label: "_opportunities".loc(),
parameterWidget: "XV.OpportunityListParameters",
components: [
query: {orderBy: [
{attribute: 'number'}
]},
- allowPrint: true,
parameterWidget: "XV.ProspectListParameters",
components: [
{kind: "XV.ListItem", components: [
label: "_salesOrders".loc(),
collection: "XM.SalesOrderListItemCollection",
parameterWidget: "XV.SalesOrderListParameters",
- actions: [],
+ actions: [
+ {name: "print", privilege: "ViewSalesOrders", method: "doPrint", isViewMethod: true},
+ {name: "email", privilege: "ViewSalesOrders", method: "doEmail", isViewMethod: true}
+ ],
query: {orderBy: [
{attribute: 'number'}
]},
{attribute: 'dueDate'},
{attribute: 'name'}
]},
- allowPrint: true,
components: [
{kind: "XV.ListItem", components: [
{kind: "FittableColumns", components: [
query: {orderBy: [
{attribute: 'number'}
]},
- allowPrint: true,
parameterWidget: "XV.VendorListParameters",
components: [
{kind: "XV.ListItem", components: [
enyo.kind({
name: "XV.Postbooks",
kind: "XV.ModuleContainer",
+ handlers: {
+ onNoBaseCurr: "handleNoBaseCurr"
+ },
modules: [
{name: "welcome", label: "_welcome".loc(), hasSubmenu: false,
panels: [
welcome.setAttributes({src: url + params});
}
this.inherited(arguments);
+ },
+ handleNoBaseCurr: function () {
+ var that = this,
+ wsCallback = function (model) {
+ // If workspace was not saved, prompt again.
+ if (model) {
+ return;
+ } else {
+ that.handleNoBaseCurr();
+ }
+ };
+
+ this.notify(this, {
+ type: XM.Model.QUESTION,
+ message: "_selectBaseCurrency".loc(),
+ yesLabel: "_setBaseCurrToUSD".loc(),
+ noLabel: "_createBaseCurr".loc(),
+ callback: function (response) {
+ if (!response.answer) {
+ // User doesn't want to use USD, open Currency workspace
+ that.addWorkspace(null, {
+ workspace: "XV.CurrencyWorkspace",
+ attributes: {
+ isBase: true
+ },
+ callback: wsCallback
+ });
+
+ // User confirms that they want to use USD, open USD workspace, set isBase
+ } else if (response.answer) {
+ that.addWorkspace(null, {
+ workspace: "XV.CurrencyWorkspace",
+ id: "USD",
+ attributes: {
+ isBase: true
+ },
+ callback: wsCallback,
+ success: function () {
+ this.$.isBase.setValue("true");
+ }
+ });
+ }
+ }
+ });
}
});
classes: "in-panel", components: [
{kind: "XV.InputWidget", attr: "abbreviation"},
{kind: "XV.InputWidget", attr: "name"},
- {kind: "XV.InputWidget", attr: "symbol"}
+ {kind: "XV.InputWidget", attr: "symbol"},
+ {kind: "XV.CheckboxWidget", attr: "isBase", name: "isBase"}
]}
]}
]}
label: "_print".loc(),
privilege: "PrintInvoices",
prerequisite: "isReadyClean"
+ },
+ {
+ name: "email",
+ isViewMethod: true,
+ label: "_email".loc(),
+ privilege: "PrintInvoices",
+ prerequisite: "isReadyClean"
}],
components: [
{kind: "Panels", arrangerKind: "CarouselArranger",
onPaymentPosted: 'handlePaymentPosted',
},
model: "XM.SalesOrder",
+ actions: [{
+ name: "print",
+ isViewMethod: true,
+ label: "_print".loc(),
+ privilege: "ViewSalesOrders",
+ prerequisite: "isReadyClean"
+ },
+ {name: "email",
+ isViewMethod: true,
+ label: "_email".loc(),
+ privilege: "ViewSalesOrders",
+ prerequisite: "isReadyClean"
+ }],
components: [
{kind: "Panels", arrangerKind: "CarouselArranger",
fit: true, components: [
{kind: "XV.DateWidget", attr: "packDate"},
{kind: "XV.InputWidget", attr: "formatStatus",
label: "_status".loc()},
+ {kind: "XV.CheckboxWidget", attr: "printOnSaveSetting",
+ label: "_printOnSave".loc()},
{kind: "onyx.GroupboxHeader", content: "_billTo".loc()},
{kind: "XV.SalesCustomerWidget", attr: "customer",
name: "customerWidget", showAddress: true,
{kind: "XV.SalesOrderDocumentsBox", attr: "documents"}
]}
],
+ /**
+ * When the printOnSaveSetting checkbox is changed,
+ * also change the workspace setting.
+ */
+ controlValueChanged: function (inSender, inEvent) {
+ this.inherited(arguments);
+ if (inEvent.originator.attr === 'printOnSaveSetting') {
+ this.printOnSaveSetting = inEvent.originator.value;
+ }
+ },
/**
* @listens onPaymentPosted
*/
"_creditMemo": "Credit Memo",
"_current": "Current",
"_currentDate": "Current Date",
+ "_customerAddress": "Customer Address",
"_customerDefaults": "Customer Defaults",
"_customerTypes": "Customer Types",
"_cutOffDay": "Cutoff Day",
"_pricing": "Pricing",
"_pricingOnLineItemEdits": "Pricing on Line Item edits",
"_printCreditMemos": "Print Credit Memos",
- "_printOnSave": "Print on Save",
+ "_printSalesOrder": "Print Sales Order",
"_process": "Process",
"_processCreditCards": "Process Credit Cards",
"_prompt": "Prompt",
"_salesDescription": "Customer and Sales Order Management",
"_salesHistory": "Sales History",
"_salesOrder": "Sales Order",
+ "_salesOrderAck": "Sales Order Acknowledgement",
"_scheduled": "Scheduled",
"_scheduledDate": "Scheduled Date",
"_shipControl": "Ship Control",
"_shipDate": "Ship Date",
+ "_shipTo": "Ship To",
"_showQuotesAfterConverted": "Show Quotes after Conversion to SO",
"_showSaveAndAddbutton": "Show 'Save and Add to Packing List' Button on Sales Order",
"_staleAnalysisWarning": "Free trial demo analysis data will not be updated from your live changes.",
label: "_nextNumber".loc(), formatting: false},
{kind: "XV.ToggleButtonWidget", attr: "DefaultPrintSOOnSave",
label: "_printOnSave".loc()},
-
{kind: "onyx.GroupboxHeader", content: "_quote".loc()},
{kind: "XV.NumberPolicyPicker", attr: "QUNumberGeneration",
label: "_number".loc() + " " + "_policy".loc()},
"loadOrder": 20,
"databaseScripts": [
"xt/tables/acttype.sql",
+ "xt/tables/rptdef.sql",
"xt/views/share_users_cohead.sql",
"xt/views/share_users_cust.sql",
"xt/views/share_users_shipto.sql",
--- /dev/null
+select xt.add_report_definition('XM.SalesOrder', 0, $${
+ "settings": {
+ "detailAttribute": "lineItems",
+ "defaultFontSize": 12,
+ "defaultMarginSize": 20
+ },
+ "headerElements": [
+ {
+ "element": "image",
+ "definition": "Logo",
+ "options": {"x": 40, "y": 25, "width": 250}
+ },
+ {
+ "definition": [{"text": "_salesOrderAck"}],
+ "options": {"fontBold": true, "fontSize": 18, "x": 300, "y": 40, "width": 300, "align": "right"}
+ },
+ {
+ "definition": [{"attr": "number"}],
+ "options": {"x": 300, "y": 70, "width": 280, "align": "right"}
+ },
+ {
+ "definition": [{"attr": "orderDate"}],
+ "options": {"x": 300, "y": 90, "width": 280, "align": "right"}
+ },
+ {
+ "definition": [{"text": "_customerAddress", "label": true}],
+ "options": {"x": 0, "y": 140, "fontBold": true}
+ },
+ {
+ "definition": [
+ {"attr": "billtoName"},
+ {"attr": "billtoAddress1"},
+ {"attr": "billtoAddress2"},
+ {"attr": "billtoAddress3"},
+ {"attr": "billtoCity"},
+ {"attr": "billtoState"},
+ {"attr": "billtoPostalCode"},
+ {"attr": "billtoCountry"},
+ {"attr": "billtoPhone"}
+ ],
+ "transform": "address",
+ "options": {"x": 0, "y": 160, "width": 250}
+ },
+ {
+ "definition": [{"text": "_billTo", "label": true}],
+ "options": {"x": 225, "y": 140, "fontBold": true}
+ },
+ {
+ "definition": [
+ {"attr": "billtoName"},
+ {"attr": "billtoAddress1"},
+ {"attr": "billtoAddress2"},
+ {"attr": "billtoAddress3"},
+ {"attr": "billtoCity"},
+ {"attr": "billtoState"},
+ {"attr": "billtoPostalCode"},
+ {"attr": "billtoCountry"},
+ {"attr": "billtoPhone"}
+ ],
+ "transform": "address",
+ "options": {"x": 225, "y": 160, "width": 250}
+ },
+ {
+ "definition": [{"text": "_shipTo", "label": true}],
+ "options": {"x": 425, "y": 140, "fontBold": true}
+ },
+ {
+ "definition": [
+ {"attr": "shiptoName"},
+ {"attr": "shiptoAddress1"},
+ {"attr": "shiptoAddress2"},
+ {"attr": "shiptoAddress3"},
+ {"attr": "shiptoCity"},
+ {"attr": "shiptoState"},
+ {"attr": "shiptoPostalCode"},
+ {"attr": "shiptoCountry"},
+ {"attr": "shiptoPhone"}
+ ],
+ "transform": "address",
+ "options": {"x": 425, "y": 160, "width": 250}
+ },
+ {
+ "definition": [{"text": "_purchaseOrderNumber", "label": true}],
+ "options": {"fontBold": true, "x": 0, "y": 230}
+ },
+ {
+ "definition": [{"attr": "customerPurchaseOrderNumber"}],
+ "options": {"x": 0, "y": 245}
+ },
+ {
+ "definition": [{"text": "_terms", "label": true}],
+ "options": {"fontBold": true, "x": 150, "y": 230}
+ },
+ {
+ "definition": [{"attr": "terms.description"}],
+ "options": {"x": 150, "y": 245}
+ },
+ {
+ "definition": [{"text": "_shipDate", "label": true}],
+ "options": {"fontBold": true, "x": 250, "y": 230}
+ },
+ {
+ "definition": [{"attr": "scheduleDate"}],
+ "options": {"x": 250, "y": 245}
+ },
+ {
+ "definition": [{"text": "_shipVia", "label": true}],
+ "options": {"fontBold": true, "x": 325, "y": 230}
+ },
+ {
+ "definition": [{"attr": "shipVia"}],
+ "options": {"x": 325, "y": 245}
+ },
+ {
+ "definition": [{"text": "_fob", "label": true}],
+ "options": {"fontBold": true, "x": 500, "y": 230}
+ },
+ {
+ "definition": [{"attr": ""}],
+ "options": {"x": 500, "y": 245}
+ },
+ {
+ "element": "band",
+ "definition": [
+ {"text": "_item", "width": 100},
+ {"text": "_description", "width": 100},
+ {"text": "_ordered", "width": 80},
+ {"text": "_balance", "width": 80},
+ {"text": "_uom", "width": 50},
+ {"text": "_unitPrice", "width": 90},
+ {"text": "_amount", "width": 70}
+ ],
+ "options": {"border": 0, "padding": 5, "x": 0, "y": 325}
+ },
+ {"element": "bandLine", "size": 2}
+ ],
+ "detailElements": [
+ {"element": "fontNormal"},
+ {
+ "element": "band",
+ "definition": [
+ {"attr": "lineItems*item.number", "width": 100},
+ {"attr": "lineItems*item.description1", "width": 100},
+ {"attr": "lineItems*quantity", "width": 80},
+ {"attr": "lineItems*balance", "width": 80},
+ {"attr": "lineItems*quantityUnit", "width": 50},
+ {"attr": "lineItems*price", "width": 90},
+ {"attr": "lineItems*extendedPrice", "width": 70}
+ ],
+ "options": {"fontBold": true, "border": 0, "padding": 14}
+ }
+ ],
+ "footerElements": [
+ {
+ "definition": [
+ {"attr": "subtotal", "label": true},
+ {"attr": "miscCharge", "label": true},
+ {"attr": "taxTotal", "label": true},
+ {"attr": "total", "label": true},
+ {"attr": "balance", "label": true}
+ ],
+ "options": {"fontBold": true, "fontSize": 14, "width": 550, "align": "right"}
+ }
+ ],
+ "pageFooterElements": [
+ {
+ "element": "pageNumber", "definition": [],
+ "options": {"align": "center"}
+ }
+ ]
+}$$);
details = XT.session.details;
loginInfo.setContent(details.username + " ยท " + details.organization);
this.state = RUNNING;
+ that.startupProcess();
+
+ // TODO - 7. Initiate Empty Database Startup "checklist" process for empty/quick start databases
+ } else if (this.state === RUNNING) {
+ // No process in place so proceed to activate
XM.Tuplespace.trigger("activate");
XT.app.$.postbooks.activate();
+
+ // Send no Base Currency event
+ if (!XT.baseCurrency()) {
+ this.waterfallNoBaseCurr();
+ }
}
},
start: function (debug) {
- if (this.getIsStarted()) { return; }
+ if (this.getIsStarted()) {return; }
XT.app = this;
this.setDebug(debug);
togglePullout: function (inSender, inEvent) {
this.$.pullout.togglePullout(inSender, inEvent);
},
+ waterfallNoBaseCurr: function (inSender, inEvent) {
+ this.$.postbooks.waterfall("onNoBaseCurr", inEvent);
+ return true;
+ },
waterfallSearch: function (inSender, inEvent) {
this.$.postbooks.waterfall("onSearch", inEvent);
return true; // don't want to double up
});
row.createComponents(columns, {owner: this});
},
-
+ /**
+ Show the report in another tab and download pdf.
+ */
+ doDownload: function (options) {
+ this.openReport(XT.getOrganizationPath() + options.model.getReportUrl("download"));
+ },
+ /**
+ If email is available, email the report. Otherwise, show the report in
+ another tab.
+ */
+ doEmail: function (options) {
+ if (XT.session.config.emailAvailable) {
+ // send it to be emailed silently by the server
+ options.model.doEmail();
+ } else {
+ this.openReport(XT.getOrganizationPath() + options.model.getReportUrl());
+ }
+ },
+ /**
+ If a printer is available, print the report. Otherwise, show the report in
+ another tab.
+ */
+ doPrint: function (options) {
+ if (XT.session.config.printAvailable) {
+ // send it to be printed silently by the server
+ options.model.doPrint();
+ } else {
+ this.openReport(XT.getOrganizationPath() + options.model.getReportUrl());
+ }
+ },
+ /**
+ Open the report pdf in a new tab
+ */
+ openReport: function (path) {
+ window.open(path, "_newtab");
+ },
/**
@todo Document the getModel method.
*/
}
}
},
+ // TODO: in 1.8.0 make this the default, move the buttons into a gear
+ // menu, and follow the same option convention as in the list
+ download: function () {
+ this.openReport(XT.getOrganizationPath() + this.getValue().getReportUrl("download"));
+ },
/**
- Print the model's data, either silently or by opening a tab
-
- TODO: in 1.8.0 make this the default, move the buttons into a gear
- menu, and follow the same option convention as in the list
-
+ Email the model's data, either silently or by opening a tab
*/
+ email: function () {
+ if (XT.session.config.emailAvailable) {
+ // send it to be printed silently by the server
+ this.getValue().doEmail();
+ } else {
+ this.openReport(XT.getOrganizationPath() + this.getValue().getReportUrl());
+ }
+ },
+ /**
+ Print the model's data, either silently or by opening a tab
+ */
print: function () {
if (XT.session.config.printAvailable) {
// send it to be printed silently by the server
this.getValue().doPrint();
} else {
- // no print server set up: just pop open a tab
- window.open(XT.getOrganizationPath() + this.getValue().getReportUrl(), "_newtab");
+ this.openReport(XT.getOrganizationPath() + this.getValue().getReportUrl());
}
},
+ /**
+ Open the report pdf in a new tab
+ */
+ openReport: function (path) {
+ window.open(path, "_newtab");
+ },
/**
Handle clearing and reseting of model if the record id changes.
*/
if (printFormat && !prop.toOne && !prop.toMany) {
switch(prop.attr.type) {
case "Date":
+ case "DueDate":
preOffsetDate = item[itemAttr];
offsetDate = preOffsetDate &&
new Date(preOffsetDate.valueOf() + 60000 * preOffsetDate.getTimezoneOffset());
formattedContent[key] = XT.String.formatBraces(reportData[0], value);
}
});
+
formattedContent.text = formattedContent.body;
formattedContent.attachments = [{fileName: reportPath, contents: data, contentType: "application/pdf"}];
@description The InvoiceList should be printable
*/
it("XV.InvoiceList should be printable", function () {
- var list = new XV.InvoiceList();
- assert.isTrue(list.getAllowPrint());
+ var list = new XV.InvoiceList(),
+ actions = list.actions;
+ assert.include(_.pluck(actions, 'name'), 'print');
+ assert.include(_.pluck(actions, 'name'), 'email');
});
});
.prototype.model.prototype.recordType;
assert.equal(attrModel, widgetModel);
});
+ /**
+ @member Buttons
+ @memberof Invoice
+ @description The InvoiceWorkspace should be printable
+ */
+ it("XV.InvoiceWorkspace should be printable", function () {
+ var workspace = new XV.InvoiceWorkspace(),
+ actions = workspace.actions;
+ assert.include(_.pluck(actions, 'name'), 'print');
+ assert.include(_.pluck(actions, 'name'), 'email');
+ });
/**
@member Navigation
@memberof Invoice
*/
it("XV.ReturnList should be printable", function () {
var list = new XV.ReturnList();
- assert.isTrue(list.getAllowPrint());
+ // TODO: implement printing on Returns
+ //assert.isTrue(list.getAllowPrint());
});
});
}), "isSalesOrders");
});
});
+ describe("Sales Order list", function () {
+ /**
+ @member Buttons
+ @memberof Invoice
+ @description The InvoiceWorkspace should be printable
+ */
+ it("XV.SalesOrderList should be printable", function () {
+ var list = new XV.SalesOrderList(),
+ actions = list.actions;
+ assert.include(_.pluck(actions, 'name'), 'print');
+ assert.include(_.pluck(actions, 'name'), 'email');
+ });
+ });
+ describe("Sales Order workspace", function () {
+ /**
+ @member Buttons
+ @memberof SalesOrder
+ @description The SalesOrderWorkspace should be printable
+ */
+ it("XV.SalesOrderWorkspace should be printable", function () {
+ var workspace = new XV.SalesOrderWorkspace(),
+ actions = workspace.actions;
+ assert.include(_.pluck(actions, 'name'), 'print');
+ assert.include(_.pluck(actions, 'name'), 'email');
+ });
+ });
describe("Sales order workflow", function () {
var salesOrderModel,
saleTypeModel,