Disabling Override in Address Box - netsuite

I am open to doing this via Forms, Workflows, or Suitescript. None have worked for me so far.
On a transaction, a user can change the bill to or ship to address for a customer. We are having issues due to the users using the Override feature and not the normal "Address Line 1, City, State, Zip" lines. Therefore, we want to disable the override functionality.
I cannot find this on any forms. I have tried workflows - I have disabled it on Before Record Load, Before User Edit, and Before field edit. I could not hide nor disable the Override button in any of these cases. I also tried hiding/disabling the Address free form text box they type in after they hit Override. I did this in all of the above stages as well as After Field Edit for when the Override button is pushed. Lastly, I attempted to just make the address fields mandatory. To do this, I tried setting Address Line 1, City, State, Zip all mandatory and again I tried before record load, before user edit, and before field edit. None actually worked. The workflow in any case would say it fired on Before Record load but when I went to add or edit an address, it still worked.
Part of my confusion comes on what exactly an address is. While the user is doing this on the transaction level (Quote, Sales Order, or Invoice), technically the update stores on the Customer Level. I tried applying the same above workflows on the Customer level with no success.
I am about to try scripting against this, but don't feel very optimistic based on all of the above testing with Workflows.
Has anyone else tried to do any manipulation against the Address on the transaction level? How did you do that? Again, I am open to forms, workflows, or Scripts. If you did it outside of these, please explain.
EDIT:
I still need help with this. This problem is persisting. Has anyone found a way to disable the "Override" feature on a transaction but still allow the drop down?

This seems to work to disable the drop-down select list for the Address on a transaction. I only tested it on a sales order but the theory should apply to other transactions as well.
var DcDisableAddress = {
beforeLoad : function(type, form) {
if (type == 'edit') {
var shipSelect = form.getField('shipaddresslist');
if (shipSelect) {
shipSelect.setDisplayType('disabled');
}
}
}
}

Use below as custom code in your address form.
/**
*#NApiVersion 2.0
*#NScriptName
*#NScriptType ClientScript
*/
define(['N/currentRecord'],function(currentRecord) {
function pageInit(context) {
var field = context.currentRecord.getField({
fieldId: 'override'
});
field.isDisabled = true;
}
return {
pageInit: pageInit
};
});

Related

Changing product price in Shopware 6 dynamically

I would like to change the price of a product based on the customer's selection. For example, I'm trying to build a small PDP widget to make customers able to choose the number of candles on a cake or write text on cakes and update the price accordingly. The docs only cover how to change the price by overwriting the cart's collector/processor but I don't want to use this method because of other plugins potentially overwriting the same service. So, is there are any other methods of changing the price of the products by subscribing to an event?
There are a few things you will need to consider in this one.
Firstly, you will need to save the user input data somewhere (amount of candles, text).
Possibly a separate database table that has a OneToMany relationship on cart line items. See this article. Und ya, this is also the part where you will hook into the onLineItemAdd event & save your user input to that table. You may as well also subscribe to the onLineItemUpdate for the same saving logic. You could do the same when removing the item from the cart, although that may not be necessary if you use database's "CASCADE on delete" when implementing your DB table. Meaning once the line item gets removed by the customer (deleted in the DB), your database entry gets deleted as well.
Afterwards, you can then use the extensions or otherwise called associations to pull this data on the cart page & the order pages. You can be a little more fancy here, if you look at all the frontend router calls, you will notice that Shopware sometimes passes "Criteria" class you can hook into.
public static function getSubscribedEvents(): array
{
return [
OrderRouteRequestEvent::class => 'alterCriteria',
DocumentOrderCriteriaEvent::class => 'alterCriteria',
];
}
public function alterCriteria(Event $event): void
{
if (method_exists($event, 'getCriteria')) {
$event->getCriteria()->addAssociation('lineItems.myExtension'); // check syntax, could be lineItem.
}
}
Now you can extend the twig templates to show your candles or text in the order page, cart page, document (invoice) pages.
Secondly, you will have to handle the price. This part will be easier now that you have data saved & being automatically pulled via criteria subscribers. If it's not possible to hook into those events all the time, you will still have an option to manually load your data.
I do not recommend modifying the price itself, but maybe you could look into adding a surcharge instead. Maybe this article will be helpful to understand the price flow. You could also see if there are any other plugins out there that implement surcharge logic to see it in action.

Workaround to search Netsuite Note record by Customer id

I'm trying to get an app I'm working on to display all associated user notes for a given Customer record (as it appears on the UI Customer record page in Netsuite proper).
To that end, I've set up a Netsuite RESTlet to return a list of internal ids for associated Note records given a Customer internal id.
I've set up a simple search in the RESTlet script:
function get_notes(params) {
log("GET params", JSON.stringify(params));
var filters = [
new nlobjSearchFilter('internalid', 'customer', 'is', params.id)
];
var columns = [
new nlobjSearchColumn('internalid'),
new nlobjSearchColumn('note'),
];
var search = nlapiCreateSearch('note', filters, columns);
var notes = search.runSearch().getResults(0, 3);
return notes;
}
function log(msg, details) {
nlapiLogExecution('DEBUG', msg, details);
}
The script works as expected, but the problem is that this search ONLY returns Notes for which the author field (which is a user internal id) matches the internal id of the user performing the search. Meaning - you can only search for Notes for which you are the author.
I have been informed that this is a 'feature' of Netsuite for some unfathomable security reason.
I need to be able to get a list of all the associated Note ids, not just those for which the user making the request is the author.
Any ideas on a workaround to get at all the associated Notes? A different way to structure the search? Some kind of secret way to define your own custom Search Joins?
I can't even find documentation on this behavior (blocking Note searches from non-authors). Perhaps someone knows how to override it at the admin level?
I'm not quite ready to admit that this is impossible yet.
NB: User Note is a Note-type record associated with the Customer record, not a field on Customer record, so I can't access it directly from Customer. There is also not a Search Filter or Search Join for Note or User Note.
Using RESTlets you cannot get the notes of other users unless you invoke the RESTlet using credentials/tokens of roles like Administrator/Full Access. RESTlets always runs in the context of current user.
One alternative to do that, if you really got to achieve this any how:
1) Create a user event script on customer which creates a custom record that simulates the functionality of system notes.
2) Make sure that the RESTlet user roles have full level of access on the custom record and make customer as parent of your custom record.
3) In your RESTlet return the custom records.
Basically RESTLETS always run as the user who invokes them.
If you can use a Suitelet for this you can set that up to run as Administrator and can return any Notes you can craft a search for.
Are you actually needing a Restlet ? i.e. Are you calling this from an external application or are you trying to add functionality in the NS GUI? If the latter then you can easily use a Suitelet.

Suitescript - Hiding line fields during Sales Order/Invoice entry

I'm wondering if anyone knows a way to HIDE certain fields (such as costs) from certain Netsuite roles if they are not permitted to see costs.
I can prevent users changing sell prices without the proper authority with nlapiDisableLineItemField during PostSourcing and validateline etc...
But with cost fields, I'd like to HIDE them if the user does not have COST access. I realize I can do this by creating a separate form that does not include costs, but if I can hide information via the script, it means less duplication of effort down the track with other things I have in mind.
You can use a beforeLoad userevent script to hide body level fields (but, it is not possible to do the same for line item field, as there isn't any API on nlobjform to allow that. For sublist/lineitem fields You will have to write a client script validations or remove the field from the form like you have been already doing as you mentioned in your question).
In you beforeload user event script you get access to form and then use something like below to hide body level fields.
function beforeLoadEntryFunction(type, form)
{
if(nlapiGetRole() === 'NON_ACCESSIBLE_ROLE_ID'){
form.getField(YOUR_BODY_FIELD_ID).setDisplayType('hidden');
}
}
Edit:
For sublist/lineitem fields create a client script with code as
function clientScriptEntryFunction(type, form)
{
if(nlapiGetRole() === 'NON_ACCESSIBLE_ROLE_ID'){
form.getField(YOUR_BODY_FIELD_ID).setDisplayType('hidden');
nlapiDisableLineItemField(SUBLIST_ID, LINE_FIELD_ID);
}
}
And in before load user event use form.setScript(YOUR_CLIENT_SCRIPT_ID) as you already have access to the form object.
Remember, client script should be a global client script
If your purpose is purely aesthetic, you can do a Client side onLoad script and hide the fields via jQuery, you can do a select by name which wouldn't change even on version upgrades.
The jQuery library is included on NetSuite.

NetSuite, prevent Quote to Sales Order (via Sales Order button) if prospect assigned vs customer

We allow sales to attach Prospects to an Opportunity and Quote, and once credit has qualified the prospect they promote the prospect to a customer. What we need to do is hide the "Sales Order" button on the quote, or disallow advancing the quote to a sales order.
I was hesitant to ask this- seems like it should be intuitive to figure out. I looked at the standard NetSuite button id's in NetSuite help but there wasn't one for "Sales Order". I've looked at validation logic but this isn't validation as the sales order button is shown when record is not in edit mode. If possible I'd like the solution to be form independent.
I'd be happy to hide the button or letting the user click the button and preventing them from creating the sales order. It might be more user friendly doing the latter because if the button is hidden sales will be calling asking why the button is not there.
For clarity here is an image:
I am assuming that when you are talking about "the Sales Order button", you mean this one:
I'm not sure if this is the best user experience, or if you have NetSuite development resources available to you, but here is one option:
Create a new User Event script that is deployed to the Sales Order (and any other Transaction record you may want this prevention on). Using the BeforeLoad event, you can check if the Entity on the Transaction is in the Prospect stage. If they are, then the script will throw an error, preventing the creation of the Transaction. Code to accomplish this:
function onBeforeLoad(type) {
var entityId = nlapiGetFieldValue('entity');
if ((type != 'create') || !entityId) { return; }
if(nlapiLookupField('customer', nlapiGetFieldValue('entity'), 'stage') === 'PROSPECT') {
throw nlapiCreateError('INVALID_REQUEST', 'You cannot create a Sales Order from a Quote placed for a Prospect');
}
}
I tested this code in a TSTDRV account, and it works as expected. You might alternatively be able to build a workflow that does the same thing without requiring you to write code, but I did not attempt this.
By using a User Event script, this code will be form independent as well as entry point independent, meaning that this code will execute if the Sales Order is being created through the UI, through some other script, through a web services integration (depending on your web services configuration), or through a CSV import (depending on your CSV import configuration).
To hide the option:
If you're referring to the dropdown list, you can create a script for context view/edit to do the following:
setFieldAndLabelVisibility("nl13", false);
Otherwise, replace nl13 with the value of the table or td element shown when you inspect element on the desired Sales Order link/icon.
--The ID in the example above is the table, button or label ID shown when you inspect element

NetSuite: Issue turning a quote into a sales order

I have two business requirements that are currently conflicting with each other. I added the following logic to the client-side order creation code, to restrict who could order by invoice:
if (type == 'create' && nlapiGetContext().getRoleCenter() == 'CUSTOMER') {
if(nlapiGetFieldValue('entity')){// shouldn't be here if no entity
var hasTerms = nlapiLookupField('customer', nlapiGetFieldValue('entity'), 'terms');
var neededFormId = hasTerms ? 135 : 134;
if (req && !req.getParameter('cf') && neededFormId != nlapiGetFieldValue('customform')) {
nlapiSetRedirectURL('RECORD', nlapiGetRecordType(), nlapiGetRecordId(), (type == 'create'), { cf: neededFormId });
}
}
}
However, for some reason, this has now broken the following needed use case: When I now click "Create Order" from a Quote, it creates it but with none of the items from the quote in the order any more. When I comment out the above logic , the "Create Order" button works fine. How can I get both? Can I somehow check if the order is being created as a result of an existing quote or not?
Have you tried getting the value of the 'createdfrom' field on the Page Init event? If you are creating standalone SO, this field will be blank.
Use "createdfrom" check as suggested by #rusty to avoid Quote converted SO to fall into your logic's trap.
However, you still may want to use the specific form, in that case you can write the logic in user event script to change the form.
If the purpose of the form is to ask for different fields which does not appear in the other form, you can try with a "beforeload user event script" which gives access to nlobjform and you can try changing the fields on the form.
Consider doing the checking when making the initial Quote form available to the client. Terms customers get the Terms quote form. Credit customers get a quote form that will always lead them to a Cash Sale.
Then just use Netsuite's inherent on the quote forms.
Cheers

Resources