NetSuite Advanced PDF Creation via Button - netsuite

I've created a button on an estimate form to print an advanced PDF.
However, I get the below error in the log
java.lang.java.lang.StringIndexOutOfBoundsException: String index out of range: 0
I've read somewhere it might have to do with images in the template, but I have tried taking them out and still get the error.
Does anyone have any idea for me about this?
The code to generate/render the PDF is:
* #NApiVersion 2.x
* #NScriptType Suitelet
* #NModuleScope Public
*/
define([
'SuiteScripts/Directory/Library.js'
, 'N/render'
, 'N/record'
],
function (Library, render, record)
{
/**
* Main entry function
*
* #param {Object} context
* #returns {Void}
*/
function PrintPriceIncreaseQuote(context)
{
var renderer = null;
try
{
if (context.request.method == 'GET')
{
renderer = createRenderer(context);
printTemplate(context.response, renderer);
}
}
catch (e)
{
Library.errorHandler('PrintPriceIncreaseQuote', e);
}
}
/**
* Create renderer
*
* #param {Object} context
* #returns {Object} renderer
*/
function createRenderer(context)
{
var renderer = null;
var recordId = 0;
try
{
recordId = context.request.parameters.id;
//Create the renderer object
renderer = render.create();
renderer.setTemplateByScriptId('CUSTTMPL_125_4099_SB7_165');
renderer.addRecord({templateName: 'record',
record: record.load({
type: record.Type.ESTIMATE,
id: recordId
})
});
}
catch (e)
{
Library.errorHandler('createRenderer', e);
}
return renderer;
}
/**
* Print merged template
*
* #param {Object} response
* #param {Object} renderer
* #returns {Void}
*/
function printTemplate(response, renderer)
{
var pdfFile = null;
try
{
pdfFile = renderer.renderAsPdf();
response.writeFile({file: pdfFile, isInline: true});
}
catch (e)
{
Library.errorHandler('printTemplate', e);
}
}
return {
onRequest: PrintPriceIncreaseQuote
};
});
'''/**

I tried your code, it works well with my XML/PDF templates. Check the XML DOM structure.

Related

How to upload files to AWS S3 from NestJS ( Suggestion )

im working in my reutilizable code, and i have for you
a FileService to Upload files to AWS S3 with NestJS.
The if conditional that you see in the code about cloudPlatform variable
is because this is not the final code.
Eventually this service will be able to upload to many cloud platforms like
GCP, Azure, AWS and FileSystem.
import { Injectable, Logger, NotFoundException, InternalServerErrorException } from '#nestjs/common';
import { ConfigService } from '#nestjs/config';
import { S3 } from 'aws-sdk';
import * as moment from 'moment';
import { v4 as uuid } from 'uuid';
import { IAWS_S3 } from './interfaces/aws-s3.interface';
import { Response } from 'express';
#Injectable()
export class FileService {
/**
*
* #variable cloudPlatform is the tecnology to save files in the cloud
* #variable awsConfig is the Amazon Web Service S3 configuration
* #S3 is the S3 to instanciate your credentials to use Amazon Web Service
*/
private logger = new Logger('FileService');
private cloudPlatform: string = this.configService.get('uploadFilesSettings').fileUploadPlatform;
private awsConfig: IAWS_S3;
private s3: S3;
constructor(
private readonly configService: ConfigService,
) {
if ( this.cloudPlatform === 'AWS_S3' ) {
this.awsConfig = this.configService.get<IAWS_S3>('aws');
this.s3 = new S3( this.awsConfig );
}
}
/**
* * Function to upload files sent from the body
* #param files of the request body in an object
* #returns an object with properties that are an string array
* like this obj = { prop1: ['a.jpg','b.jpg'], prop2: ['test.gif'] ...prop n }
*/
async uploadFiles<T, U>( files: T ): Promise<U> {
let props = Object.keys(files);
let arrPromisesPending = await this.getArrayToUpload<T>( props, files );
let arrPromisesDone = await Promise.all(
arrPromisesPending.map( async( file: Express.Multer.File ) => {
return {
fieldname: file.fieldname,
...( await this.uploadFileTo( file, this.cloudPlatform )),
}
})
)
return await this.getUploadedFiles<U>( arrPromisesDone, props );
}
/**
* * Function to get an array of objects of the files sent from the body
* * to make a Promise.all()
* #param props all properties ( fieldname in the form-data body ) of the files object
* #param files of the request body in an object
* #returns an array of objects that every object is the file that will be uploaded
*/
async getArrayToUpload<T>( props: string[], files: T ): Promise<Object[]> {
let promises: Object[] = [];
props.map(( prop: string ) => {
files[prop].map(( file: Express.Multer.File ) => {
promises.push( file );
});
})
return promises;
}
/**
* * Function that upload the file to cloud platform
* #param file object to upload
* #param cloudPlatform site where files will be uploaded
* #returns the response of cloudPlatform
*/
async uploadFileTo( file: Express.Multer.File, cloudPlatform: string ): Promise<any> {
let type: string = file.originalname.split(".").pop();
let genericFilename: string = `${ uuid() }-${ moment().format().split('T')[0] }`;
if ( cloudPlatform === 'AWS_S3' ) {
try {
return await this.s3.upload({
Bucket: this.awsConfig.bucketName,
Key: `${ genericFilename }.${ type }`,
Body: file.buffer,
ContentType: file.mimetype,
}).promise();
} catch ( error ) {
this.logger.error( error );
throw new InternalServerErrorException('Unexpected error, check server logs');
}
}
this.logger.error('Set .env variable "FILE_UPLOAD_PLATFORM"');
throw new InternalServerErrorException('Unexpected error, check server logs');
}
/**
* * Function to format the names of the files uploaded to the cloud
* * platform and return them in an object with the corresponding
* * properties and each of these will have an array of strings
*
* #param arrPromisesDone an array of objects that were uploaded
* #param props that's means fieldnames of the files
* #returns
* ! Example of returns -----------------------------------------------------------
* ! {
* ! avatar: ['image1.png','image2.jpg', 'image3.jpeg', 'image4.jpg'],
* ! background: ['image1.png','image2.jpg', 'image3.jpeg', 'image4.jpg'],
* ! }
*/
async getUploadedFiles<T>( arrPromisesDone: Object[], props: string[] ): Promise<T> {
let uploadedFiles: any = {};
props.map(( prop: string ) => {
uploadedFiles[prop] = [];
arrPromisesDone.map(( file: any ) => {
if ( file.fieldname === prop ) {
uploadedFiles[prop].push( file.key );
}
});
});
return uploadedFiles;
}
/**
*
* #param imageName name of the image
* #param res #Res() to response from Express
* #returns the image obtained from the cloud platform to client
*/
async getFile( imageName: string, res: Response ) {
const params = { Bucket: this.awsConfig.bucketName, Key: imageName };
if ( this.cloudPlatform === 'AWS_S3' ) {
try {
const data = await this.s3.getObject( params ).promise();
res.contentType( data.ContentType );
return res.send( data.Body );
} catch ( error ) {
if ( error.statusCode === 404 )
throw new NotFoundException(`image ${ imageName } don't exist`);
this.logger.error( error );
throw new InternalServerErrorException('Unexpected error, check server logs');
}
}
this.logger.error('Set .env variable "FILE_UPLOAD_PLATFORM"');
throw new InternalServerErrorException('Unexpected error, check server logs');
}
}

use more than one v-if getting NonErrorEmittedError being thrown in vuejs?

I am able use only one v-if, but I'm trying to create step form, to separate forms input into steps and when if I put another v-if, with other v-model it gives me the following error using laravel mix and vuejs, if I just have an v-if with nothing in it's fine. It also seems that the error alert is when laravelmix compiles, but just get blank page, any ideas please?
Laravel Mix
Error:-!../../node_modules/vue-loader/lib/loaders/templateLoader.js??
vue-loader-options!../../../node_modules/vue-loader/lib/index.js??
vue-
loader-options!./Step1.vue>
vue&type=template&id=1feb510a&
NonErrorEmittedError:(Emitted value instead of an instance of Error)
app.js file
require('./bootstrap');
window.Vue = require('vue');
import Step1 from './components/Step1.vue'
new Vue({
el: '#app',
components: {
Step1
}
});
component
<template>
<form method="post" action="" class="form-group" #submit.prevent="onSubmit" #keydown="form.errors.clear($event.target.name)">
<div v-if="step === 1">
<label for="firstName" class="col-sm-2 col-form-label">What's your first name</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="first_name" name="first_name" v-model="form.first_name">
</div>
<span class="help is-danger" v-if="form.errors.has('first_name')" v-text="form.errors.get('first_name')"></span>
</div>
<div v-else>
<label for="exampleName1">What's your last name</label>
<input type="text" class="form-control" id="last_name" name="last_name" class="input" v-model="form.last_name">
<span class="help is-danger" v-if="form.errors.has('last_name')" v-text="form.errors.get('last_name')"></span>
</div>
<button class="button is-primary" :disabled="form.errors.any()">send</button>
</form>
</template>
<script>
import Form from '../Form.js';
export default {
data: function() {
return {
step:1,
errors: [],
form: new Form({
first_name: '',
last_name: ''
})
}
},
methods: {
onSubmit() {
this.form.post('/enquiry/step1')
.then(response => alert('wahoo',
));
}
}
}
Form.js
class Form {
/**
* Create a new Form instance.
*
* #param {object} data
*/
constructor(data) {
this.originalData = data;
for (let field in data) {
this[field] = data[field];
}
this.errors = new Errors();
}
/**
* Fetch all relevant data for the form.
*/
data() {
let data = {};
for (let property in this.originalData) {
data[property] = this[property];
}
return data;
}
/**
* Reset the form fields.
*/
reset() {
for (let field in this.originalData) {
this[field] = '';
}
this.errors.clear();
}
/**
* Send a POST request to the given URL.
* .
* #param {string} url
*/
post(url) {
return this.submit('post', url);
}
/**
* Send a PUT request to the given URL.
* .
* #param {string} url
*/
put(url) {
return this.submit('put', url);
}
/**
* Send a PATCH request to the given URL.
* .
* #param {string} url
*/
patch(url) {
return this.submit('patch', url);
}
/**
* Send a DELETE request to the given URL.
* .
* #param {string} url
*/
delete(url) {
return this.submit('delete', url);
}
/**
* Submit the form.
*
* #param {string} requestType
* #param {string} url
*/
submit(requestType, url) {
return new Promise((resolve, reject) => {
axios[requestType](url, this.data())
.then(response => {
this.onSuccess(response.data);
resolve(response.data);
})
.catch(error => {
this.onFail(error.response.data.errors);
reject(error.response.data.errors);
});
});
}
/**
* Handle a successful form submission.
*
* #param {object} data
*/
onSuccess(data) {
alert(data.message); // temporary
this.reset();
}
/**
* Handle a failed form submission.
*
* #param {object} errors
*/
onFail(errors) {
this.errors.record(errors);
}
}
class Errors {
/**
* Create a new Errors instance.
*/
constructor() {
this.errors = {};
}
/**
* Determine if an errors exists for the given field. removes span if not needed
*
* #param {string} field
*/
has(field) {
return this.errors.hasOwnProperty(field);
}
/**
* Determine if we have any errors.
*/
any() {
return Object.keys(this.errors).length > 0;
}
/**
* Retrieve the error message for a field.
*
* #param {string} field
*/
get(field) {
if (this.errors) {
return this.errors[field][0];
}
}
/**
* Record the new errors.
*
* #param {object} errors
*/
record(errors) {
this.errors = errors;
}
/**
* Clear one or all error fields.
*
* #param {string|null} field
*/
clear(field) {
if (field) {
delete this.errors[field];
return;
}
this.errors = {};
}
}
export default Form;
seems like I had an extra class="input" which I missed

How can I create a method that I will use in more than 1 controller in adonis?

I have this method that I will use in more than 1 controller. How can I make this method sharable?
I'm a little confused if I have to use service providers or traits...
async verificaExisteUsuarioAdministrador(){
const checkUserAdmin = await User
.findBy('username', 'admin')
if (checkUserAdmin ){
return true
}else{
return false
}
}
So, in more than one controller I need to call this function, how can I make this possible? The service providers document don't look so clear.
I advise you to create a middleware.
AdonisJS - Middleware documentation
You can configure it to run before or after the controller code.
Example
middleware :
'use strict'
/** #typedef {import('#adonisjs/framework/src/Request')} Request */
/** #typedef {import('#adonisjs/framework/src/Response')} Response */
/** #typedef {import('#adonisjs/framework/src/View')} View */
class AuthVerif {
/**
* #param {object} ctx
* #param {Request} ctx.request
* #param {Function} next
*/
async handle({ response, auth }, next) {
// call next to advance the request
/* Your code */
await next()// Controller execution
}
}
module.exports = AuthVerif
route :
Route.get("/", "youController").middleware(["authVerif"])
OR
You can create Helpers (app/Helpers/)
Example (app/Helpers/Answer.js) :
'use strict'
/**
* #summary API answer convention
*/
class Answer {
/**
* Success answer
* #param {*} data
* #returns {JSON} JSON answer
*/
static success(data) {
return { 'success': true, 'data': data }
}
}
module.exports = {
Answer
}
Import object (controllers, ...):
/** #type {typeof import('../Helpers/Answer')} */ //Documentation
const { Answer } = use('App/Helpers/Answer')

Can't get users email in Rest api used parse dashboard

I was used parse dashboard package with parse.query and get users details.
i have get all users record and parse.query to used, i getting the response but email key can't show each and every used record , the email field is show parse dashboard and mongodb table.
If your know that solution so please give me help. blow my code
var fetchUserWithIdentifier = function (userIdentifier) {
let query = new Parse.Query(User)
query.equalTo(User.Field.objectId, userIdentifier)
return query.first()
};
class User extends Parse.Object {
/**
* #return {string}
*/
get firstName() {
return this.get(User.Field.firstName)
}
/**
* #param {string} firstName
*/
set firstName(firstName) {
this.set(User.Field.firstName, firstName)
}
/**
* #return {string}
*/
get email() {
return this.get(User.Field.email)
}
/**
* #param {string} email
*/
set email(email) {
this.set(User.Field.email, email)
}
/**
* #return {string}
*/
get googleId() {
return this.get(User.Field.googleId)
}
/**
* #param {string} googleId
*/
set googleId(googleId) {
this.set(User.Field.googleId, googleId)
}
/**
* #return {string}
*/
get facebookId() {
return this.get(User.Field.facebookId)
}
/**
* #param {string} facebookId
*/
set facebookId(facebookId) {
this.set(User.Field.facebookId, facebookId)
}
/**
* #return {string}
*/
get facebookEmail() {
return this.get(User.Field.facebookEmail)
}
/**
* #param {string} facebookEmail
*/
set facebookEmail(facebookEmail) {
this.set(User.Field.facebookEmail, facebookEmail)
}
/**
* #return {boolean}
*/
get isAnonymous() {
return this.get(User.Field.isAnonymous)
}
/**
* #param {boolean} isAnonymous
*/
set isAnonymous(isAnonymous) {
this.set(User.Field.isAnonymous, isAnonymous)
}
/**
* #return {number}
*/
get deviceToken() {
return this.get(User.Field.deviceToken)
}
/**
* #param {number} deviceToken
*/
set deviceToken(deviceToken) {
this.set(User.Field.deviceToken, deviceToken)
}
/**
* #return {boolean}
*/
get isActivityVisible() {
return this.get(User.Field.isActivityVisible)
}
/**
* #param {boolean} friendActivity
*/
set isActivityVisible(isActivityVisible) {
this.set(User.Field.isActivityVisible, isActivityVisible)
}
/**
* #return {string}
*/
get deviceType() {
return this.get(User.Field.deviceType)
}
/**
* #param {string} deviceType
*/
set deviceType(deviceType) {
this.set(User.Field.deviceType, deviceType)
}
/**
* #return {string}
*/
get inviterIdentifier() {
return this.get(User.Field.inviterIdentifier)
}
/**
* #param {string} inviterIdentifier
*/
set inviterIdentifier(inviterIdentifier) {
this.set(User.Field.inviterIdentifier, inviterIdentifier)
}
/**
* #return {MeditationTime}
*/
get meditationTime() {
return this.get(User.Pointer.meditationTime)
}
/**
* #param {MeditationTime} meditationTime
*/
set meditationTime(meditationTime) {
this.set(User.Pointer.meditationTime, meditationTime)
}
/**
* #return {Parse.Relation<User, Goal>}
*/
get goals() {
return this.relation(User.Relation.goals)
}
/**
* #return {Parse.Relation<User, UserMeditationCourse>}
*/
get meditationCourses() {
return this.relation(User.Relation.meditationCourses)
}
/**
* #return {Parse.Relation<User, Friendship>}
*/
get friendships() {
return this.relation(User.Relation.friendships)
}
/**
* #return {Parse.Relation<User, UserGroupSession>}
*/
get groupSessions() {
return this.relation(User.Relation.groupSessions)
}
constructor() {
super('_User');
}
}
User.SocialType = class SocialType extends Enum { }
User.SocialType.initEnum(['facebook',
'google']);
User.Field = {
objectId: 'objectId',
email: 'email',
username: 'username',
password: 'password',
createdAt: 'createdAt',
updatedAt: 'updatedAt',
firstName: 'firstName',
// lastName: 'lastName',
googleId: 'googleId',
facebookId: 'facebookId',
facebookEmail: 'facebookEmail',
avatarPath: 'avatarPath',
isAnonymous: 'isAnonymous',
socialType: 'socialType',
inviterIdentifier: 'inviterIdentifier',
deviceToken: 'deviceToken',
deviceType: 'deviceType',
isActivityVisible: 'isActivityVisible',
}
User.Pointer = {
meditationTime: 'meditationTime'
}
User.Relation = {
goals: 'goals',
meditationCourses: 'meditationCourses',
socialAccounts: 'socialAccounts',
friendships: 'friendships',
groupSessions: 'groupSessions'
}
module.exports = User;
Try this.
var fetchUserWithIdentifier = function (userIdentifier) {
let query = new Parse.Query(User)
query.equalTo(User.Field.objectId, userIdentifier)
return query.first({ useMasterKey: true })
};

How to document module.exports defined with object.defineProperty

I'm using NodeJS and trying to get the JSDoc to property pick up what I'm doing. I have some code that looks like this:
Object.defineProperty(module, 'exports', {
enumerable: true,
configurable: true,
get: function() {
const factory = {};
/**
* Output message to the console
* #param {string} str
*/
factory.foo = function(str) {
console.log(str);
};
return factory;
}
});
Exporting foo the standard way exports.foo = function(str) { ... } is not an option in this case.
Another module can include this module has access to foo (just as if it were exported directly). For example:
var x = require('./x');
x.foo('Hello');
So how can I document this so that jsDoc picks up that this module has a function foo?
I found a way that seems to work:
Object.defineProperty(module, 'exports', {
enumerable: true,
configurable: true,
get: Factory
});
/**
* Get a factory object.
* #returns {Factory}
* #constructor
*/
function Factory() {
var factory = Object.create(Factory.prototype);
/**
* Output a message to the console.
* #name Factory#foo
* #param {string} str
*/
factory.foo = function(str) {
console.log(str);
};
return factory;
}

Resources