import declare from 'dojo/_base/declare';
import lang from 'dojo/_base/lang';
import validator from '../../Validator';
import Edit from 'argos/Edit';
import Utility from 'argos/Utility';
import getResource from 'argos/I18n';
const resource = getResource('opportunityProductEdit');
/**
* @class crm.Views.OpportunityProduct.Edit
*
* @extends argos.Edit
*
* @requires argos.Utility
*
* @requires crm.Validator
* @requires crm.Template
*/
const __class = declare('crm.Views.OpportunityProduct.Edit', [Edit], {
// Localization
titleText: resource.titleText,
detailsText: resource.detailsText,
opportunityText: resource.opportunityText,
productText: resource.productText,
productFamilyText: resource.productFamilyText,
priceLevelText: resource.priceLevelText,
priceText: resource.priceText,
basePriceText: resource.basePriceText,
discountText: resource.discountText,
adjustedPriceText: resource.adjustedPriceText,
myAdjustedPriceText: resource.myAdjustedPriceText,
baseAdjustedPriceText: resource.baseAdjustedPriceText,
quantityText: resource.quantityText,
baseExtendedPriceText: resource.baseExtendedPriceText,
extendedPriceText: resource.extendedPriceText,
extendedPriceSectionText: resource.extendedPriceSectionText,
adjustedPriceSectionText: resource.adjustedPriceSectionText,
// View Properties
entityName: 'Opportunity',
id: 'opportunityproduct_edit',
resourceKind: 'opportunityProducts',
insertSecurity: 'Entities/Opportunity/Add',
updateSecurity: 'Entities/Opportunity/Edit',
querySelect: [
'Opportunity/Description',
'Product/Name',
'Product/Family',
'Program',
'Price',
'Discount',
'AdjustedPrice',
'CalculatedPrice',
'Quantity',
'ExtendedPrice',
],
queryInclude: [
'$permissions',
],
init: function init() {
this.inherited(arguments);
this.connect(this.fields.Product, 'onChange', this.onProductChange);
this.connect(this.fields.Program, 'onChange', this.onProgramChange);
this.connect(this.fields.Discount, 'onChange', this.onDiscountChange);
this.connect(this.fields.CalculatedPrice, 'onChange', this.onAdjustedPriceChange);
this.connect(this.fields.CalculatedPriceMine, 'onChange', this.onAdjustedPriceMineChange);
this.connect(this.fields.Quantity, 'onChange', this.onQuantityChange);
},
setValues: function setValues(values) {
this.inherited(arguments);
this.fields.Program.setValue({
$key: '',
Program: values.Program,
});
if (values.Discount > 0) {
// transform the discount into a percentage number 0.10 to 10.00%
this.fields.Discount.setValue(values.Discount * 100);
}
const myCode = App.getMyExchangeRate().code;
const baseCode = App.getBaseExchangeRate().code;
this.fields.Price.setCurrencyCode(baseCode);
this.fields.CalculatedPrice.setCurrencyCode(baseCode);
if (App.hasMultiCurrency()) {
this.fields.CalculatedPriceMine.setValueNoTrigger(this._getMyRate() * values.CalculatedPrice);
this.fields.CalculatedPriceMine.setCurrencyCode(myCode);
}
this.fields.ExtendedPrice.setCurrencyCode(baseCode);
this._updateExtendedPrice();
if ((values.Product.Family !== null) && (values.Price !== null)) {
this._enableUI(true);
} else {
this._enableUI(false);
}
},
_enableUI: function _enableUI(enable) {
if (enable) {
this.fields.Discount.enable();
this.fields.Quantity.enable();
this.fields.CalculatedPrice.enable();
if (App.hasMultiCurrency()) {
this.fields.CalculatedPriceMine.enable();
}
} else {
this.fields.Discount.disable();
this.fields.Quantity.disable();
this.fields.CalculatedPrice.disable();
if (App.hasMultiCurrency()) {
this.fields.CalculatedPriceMine.disable();
}
}
},
_getMyRate: function _getMyRate() {
return App.getMyExchangeRate().rate;
},
getValues: function getValues() {
const o = this.inherited(arguments);
o.Program = o.Program.Program;
/*
* 'AdjustedPrice' is a lie. The underlying database field is actually PRICEADJUSTED and
* is a boolean, not a price that has been adjusted. Since we use the adjusted price to calculate
* the discount %, we will remove it from getValues so we aren't trying to save the wrong data type when sending
* the sdata request.
*/
delete o.AdjustedPrice;
delete o.CalculatedPriceMine;
// transform the discount back into a decimal
o.Discount = o.Discount / 100;
return o;
},
applyContext: function applyContext() {
const entry = this.options && this.options.selectedEntry;
if (entry) {
this.fields.Opportunity.setValue(entry);
}
},
onProductChange: function onProductChange(value, field) {
const selection = field && field.currentSelection;
if (selection) {
this.fields.ProductId.setValueNoTrigger(value.key);
this.fields['Product.Family'].setValueNoTrigger(selection.Family);
this.fields.Program.clearValue();
this.fields.Price.setValueNoTrigger(selection.Price);
this.fields.Discount.clearValue();
this.fields.CalculatedPrice.setValueNoTrigger(selection.Price);
if (App.hasMultiCurrency()) {
this.fields.CalculatedPriceMine.setValueNoTrigger(this._getMyRate() * selection.Price);
}
this.fields.Quantity.setValueNoTrigger(1);
this._updateExtendedPrice();
}
},
onProgramChange: function onProgramChange(value, field) {
const selection = field && field.currentSelection;
if (selection) {
this.fields.Price.setValueNoTrigger(selection.Price);
this.fields.Discount.clearValue();
this.fields.CalculatedPrice.setValueNoTrigger(selection.Price);
if (App.hasMultiCurrency()) {
this.fields.CalculatedPriceMine.setValueNoTrigger(this._getMyRate() * selection.Price);
}
this._updateExtendedPrice();
this._enableUI(true);
}
},
onDiscountChange: function onDiscountChange() {
const price = parseFloat(this.fields.Price.getValue()) || 0;
const discount = this.fields.Discount.getValue();
const adjusted = this._calculateAdjustedPrice(price, discount);
this.fields.CalculatedPrice.setValueNoTrigger(adjusted);
this._updateAdjustedPrices(adjusted);
this._updateExtendedPrice();
},
onAdjustedPriceChange: function onAdjustedPriceChange() {
const price = parseFloat(this.fields.Price.getValue()) || 0;
const adjusted = parseFloat(this.fields.CalculatedPrice.getValue()) || 0;
const discount = this._calculateDiscount(price, adjusted);
this.fields.Discount.setValueNoTrigger(discount);
if (App.hasMultiCurrency()) {
const myadjusted = this._getMyRate() * adjusted;
this.fields.CalculatedPriceMine.setValueNoTrigger(myadjusted);
}
this._updateExtendedPrice();
},
onAdjustedPriceMineChange: function onAdjustedPriceMineChange() {
const myadjusted = this.fields.CalculatedPriceMine.getValue();
const price = this.fields.Price.getValue() || 0;
const myrate = this._getMyRate();
const myprice = price * myrate; // get the price in the users exchange rate
const discount = this._calculateDiscount(myprice, myadjusted);
this.fields.Discount.setValueNoTrigger(discount);
const adjusted = this._calculateAdjustedPrice(price, discount);
this.fields.CalculatedPrice.setValueNoTrigger(adjusted);
this._updateExtendedPrice();
},
onQuantityChange: function onQuantityChange(value) {
if (isNaN(value)) {
this.fields.Quantity.setValueNoTrigger(0);
}
this._updateExtendedPrice();
},
_calculateDiscount: function _calculateDiscount(price, adjusted) {
let discount;
if (price === 0) {
discount = 0.0;
} else {
discount = (1 - (adjusted / price)) * 100;
}
return discount;
},
_calculateAdjustedPrice: function _calculateAdjustedPrice(price, discount) {
let adjusted;
if (discount === 0) {
adjusted = price;
} else {
adjusted = price - (price * (discount / 100));
}
return adjusted;
},
_updateAdjustedPrices: function _updateAdjustedPrices(adjusted) {
let myadjusted;
this.fields.CalculatedPrice.setValueNoTrigger(adjusted);
if (App.hasMultiCurrency()) {
myadjusted = this._getMyRate() * adjusted;
this.fields.CalculatedPriceMine.setValueNoTrigger(myadjusted);
}
},
_updateExtendedPrice: function _updateExtendedPrice() {
const quantity = parseFloat(this.fields.Quantity.getValue()) || 0;
const adjusted = parseFloat(this.fields.CalculatedPrice.getValue()) || 0;
const extended = adjusted * quantity;
this.fields.ExtendedPrice.setValueNoTrigger(extended);
},
onUpdateCompleted: function onUpdateCompleted() {
this._refreshOpportunityViews();
this.inherited(arguments);
},
onInsertCompleted: function onInsertCompleted() {
this._refreshOpportunityViews();
this.inherited(arguments);
},
_refreshOpportunityViews: function _refreshOpportunityViews() {
const views = [
App.getView('opportunityproduct_related'),
App.getView('opportunity_detail'),
App.getView('opportunity_list'),
];
views.forEach((view) => {
if (view) {
view.refreshRequired = true;
}
});
},
createLayout: function createLayout() {
const details = {
title: this.detailsText,
name: 'OpportunityProductDetailsEdit',
children: [{
label: this.opportunityText,
name: 'Opportunity',
property: 'Opportunity',
type: 'lookup',
textProperty: 'Description',
view: 'opportunity_related',
validator: validator.exists,
}, {
name: 'ProductId',
property: 'ProductId',
type: 'hidden',
}, {
label: this.productText,
name: 'Product',
property: 'Product',
type: 'lookup',
textProperty: 'Name',
view: 'product_related',
validator: validator.exists,
}, {
label: this.productFamilyText,
name: 'Product.Family',
property: 'Product.Family',
type: 'text',
readonly: true,
}, {
label: this.priceLevelText,
name: 'Program',
property: 'Program',
textProperty: 'Program',
type: 'lookup',
view: 'productprogram_related',
validator: validator.exists,
where: (function where() {
const val = this.fields.Product.getValue();
return `Product.Name eq "${Utility.escapeSearchQuery(val.Name)}"`;
}).bindDelegate(this),
}, {
label: App.hasMultiCurrency() ? this.basePriceText : this.priceText,
name: 'Price',
property: 'Price',
type: 'multiCurrency',
readonly: true,
}, {
label: this.discountText,
name: 'Discount',
property: 'Discount',
type: 'decimal',
notificationTrigger: 'blur',
}, {
label: this.quantityText,
name: 'Quantity',
property: 'Quantity',
type: 'decimal',
notificationTrigger: 'blur',
}],
};
if (!App.hasMultiCurrency()) {
details.children.push({
label: this.adjustedPriceText,
name: 'CalculatedPrice',
property: 'CalculatedPrice',
type: 'multiCurrency',
notificationTrigger: 'blur',
});
details.children.push({
label: this.extendedPriceText,
name: 'ExtendedPrice',
property: 'ExtendedPrice',
type: 'multiCurrency',
readonly: true,
});
}
const extendedPrice = {
title: this.extendedPriceSectionText,
name: 'OpportunityProductExtendedPriceEdit',
children: [{
label: this.baseExtendedPriceText,
name: 'ExtendedPrice',
property: 'ExtendedPrice',
type: 'multiCurrency',
readonly: true,
}],
};
const adjustedPrice = {
title: this.adjustedPriceSectionText,
name: 'OpportunityProductAdjustedPriceEdit',
children: [{
label: this.baseAdjustedPriceText,
name: 'CalculatedPrice',
property: 'CalculatedPrice',
type: 'multiCurrency',
notificationTrigger: 'blur',
}, {
label: this.myAdjustedPriceText,
name: 'CalculatedPriceMine',
property: 'CalculatedPriceMine',
type: App.hasMultiCurrency() ? 'multiCurrency' : 'hidden',
notificationTrigger: 'blur',
}],
};
const layout = this.layout || (this.layout = []);
if (layout.length > 0) {
return layout;
}
layout.push(details);
if (App.hasMultiCurrency()) {
layout.push(adjustedPrice);
layout.push(extendedPrice);
}
return layout;
},
});
lang.setObject('Mobile.SalesLogix.Views.OpportunityProduct.Edit', __class);
export default __class;