How To Present This - sharepoint

The Data
Name Date Span
Bob 12/11 0700-1530
Sue 12/11 0700-1530
Bob 12/12 0700-1530
Sue 12/12 0700-1530
Bob 12/13 0700-1530
Sue 12/13 0700-1530
Bob 12/14 0700-1530
Sue 12/14 0700-1530
Bob 12/15 0700-1530
Sue 12/15 0700-1530
Sue 12/16 1200-1830
How can I present the data as follows, with one row per person?
Sun Mon Tue Wed Thu Fri Sat
10DEC 11DEC 12DEC 13DEC 14DEC 15DEC 16DEC
Bob 0700-1530 0700-1530 0700-1530 0700-1530 0700-1530
Sue 0700-1530 0700-1530 0700-1530 0700-1530 0700-1530 1200-1830
The span might be different on different days for the same person, and there might more or fewer names for any given week. If I remember right, this is the purpose of 'cross-tab queries,' which Access can do, but I am not to sure in SharePoint.

There isn't a way to achieve that out of the box. What you'd likely need to do is use client side rendering to change the way the view is displayed. Here is a sample of a js file that changes a view's rendering (doesn't achieve what you're looking for but it's a start). The customItem function is where you'll define what each cell looks like. Then you can manipulate the results in the post render. Hopefully this can get you going down the right path. This is a good guide for getting started with CSR: https://www.codeproject.com/Articles/620110/SharePoint-Client-Side-Rendering-List-Views
(function () {
// Initialize the variable that stores the objects.
var overrideCtx = {};
overrideCtx.Templates = {};
// Assign functions or plain html strings to the templateset objects:
// header, footer and item.
overrideCtx.Templates.Header = "<B><#=ctx.ListTitle#></B>" +
"<hr><ul id='unorderedlist'>";
// This template is assigned to the CustomItem function.
overrideCtx.Templates.Item = customItem;
overrideCtx.Templates.Footer = "</ul>";
// Set the template to the:
// Custom list definition ID
// Base view ID
overrideCtx.BaseViewID = 2;
overrideCtx.ListTemplateType = 10057;
// Assign a function to handle the
// PreRender and PostRender events
overrideCtx.OnPreRender = preRenderHandler;
overrideCtx.OnPostRender = postRenderHandler;
// Register the template overrides.
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();
// This function builds the output for the item template.
// It uses the context object to access announcement data.
function customItem(ctx) {
// Build a listitem entry for every announcement in the list.
var ret = "<li>" + ctx.CurrentItem.Title + "</li>";
return ret;
}
// The preRenderHandler attends the OnPreRender event
function preRenderHandler(ctx) {
// Override the default title with user input.
ctx.ListTitle = prompt("Type a title", ctx.ListTitle);
}
// The postRenderHandler attends the OnPostRender event
function postRenderHandler(ctx) {
// You can manipulate the DOM in the postRender event
var ulObj;
var i, j;
ulObj = document.getElementById("unorderedlist");
// Reverse order the list.
for (i = 1; i < ulObj.children.length; i++) {
var x = ulObj.children[i];
for (j = 1; j < ulObj.children.length; j++) {
var y = ulObj.children[j];
if(x.innerText<y.innerText){
ulObj.insertBefore(y, x);
}
}
}
}

Related

Logic for a booking system to show available slots based on user input

I am trying to figure out the backend logic to build a car booking system where a user will choose a date and enter the amount of time he needs the car for. Then the system will generate available slots with a start and end time. Every time user returns the car the owner will wash the car for 10 minutes so the next slot's start time will be previous end + 10 minutes.
For example user books the car on 2022-09-04 and books the slot for 30 minutes. Now the available slots will be 12:00 AM-12:30 AM and the next slot will be 12:40 AM-1:10 AM and so on for the whole day. The user can choose whichever slots he wants.
Here is the UI if it helps.
Before user input: https://imgur.com/jYzQ4Oa
After user input: https://imgur.com/wkjmqtM
If another user wants to book a slot for 20 minutes I want existing available slots to adjust with that time without conflicting with the booked slots.
I have generated initial slots(no slot is booked yet) in the front end for 30minutes duration.
I will move this in the backend after I figure out the logic. I am using Nodejs and mongodb in the backend.
I haven't worked with date-time before that's why kinda struggling.
import { addMinutes} from "date-fns";
const availableSlots = [
{
id: uuidv4(),
start: new Date(date.setHours(0, 0, 0, 0)).toISOString(),//date=user selected date
end: "",
},
];
const handleSubmit = (e) => {
e.preventDefault();
const inputValue = parseInt(e.target.time.value);
if (inputValue > 0) {
let end;
let start;
const timeToWash = 10
for (let i = 0; i < 1440 / (inputValue + timeToWash); i++) {
if (i < 1) {
end = addMinutes(new Date(availableSlots[i].start), inputValue);
end = end.toISOString();
availableSlots[i] = {
id: uuidv4(),
start: availableSlots[0].start,
end: end,
};
} else {
start = addMinutes(
new Date(availableSlots[i - 1].start),
inputValue + timeToWash
);
start = start.toISOString();
end = addMinutes(new Date(start), inputValue);
end = end.toISOString();
availableSlots[i] = {
id: uuidv4(),
start: start,
end: end,
};
}
}
}
};

Building a tree structure with Gun

I am trying to implement, through Gun, a tree structure that allows to express relationships between companies, subsidiaries of these companies and their products.
The structure that I have done is as follows:
there is a root node: this is the main seller of some product (for example, sensors) and all its children (depth nodes 1) are its customers;
there are children nodes, not leaves, from level depth 1 on: these are the customers of the root knot; they can have different branches; there can be sub-sub-sub-branches of a branch and so on, there are no limits to the number of sub-subbranches;
there are leaf knots: these are the products contained in a branch, a sub-branch, a sub-sub-branch...
Here's how I thought of this:
create a client set;
put clients nodes inside client set;
create a branch set;
put branches nodes inside branch set;
link branches set to client set;
create a sensor set;
put sensors nodes inside sensor set;
link sensors set to branches set.
Somethink like this:
[clients]
/\
/ \
(MecDoland) (FrankMirros)
| |
[branches] [branches]
/ | \ |
(NY) (CA) (DA) ...
| | |
| [sensors]...
| |
| ...
[sensors]
/|\
......
Here's my implementation
const Gun = require('gun')
const gun = new Gun()
// Just a util function
function printError(ack) {
if (ack.err) {
console.log(ack.err)
}
}
// [clients]
const clients = gun.get('clients') // group
// (MecDoland)
const mac = clients.get('MecDoland').put({ data: 12 })
// (FrankMirros)
const pm = clients.get('FrankMirros').put({ data: 13 })
console.log('Adding to "clients" set MecDoland...')
// [clients] -> (MecDoland)
clients.set(mac, printError)
console.log('Adding to "clients" set philip morris...')
// [clients] -> (FrankMirros)
clients.set(pm, printError)
// [branches]
const branches = gun.get('branches') // group
// (MecDolandNY)
const macny = gun.get('MacDonaldNY').put({ data: 1 }, printError)
// (MecDolandCA)
const macca = gun.get('MecDolandCA').put({ data: 2 }, printError)
// [branches] -> (MecDolandNY)
branches.set(macny, printError)
// [branches] -> (MecDolandCA)
branches.set(macca, printError)
// [MecDoland] -> [branches]
mac.set(branches, printError)
//clients.map().once(v => console.log('CLIENT:',v))
//branches.map().once(v => console.log('BRANCH:',v._))
const sensors = gun.get('sensorsMecDolandNY') // group
const temp = gun.get('temperatue').put({ measure: 'celsius', value: 37 })
const press = gun.get('pressure').put({ measure: 'Bar', value: 2 })
sensors.set(temp)
sensors.set(press)
macny.set(sensors)
// Show all clients
gun
.get('clients')
.map()
.once(v => console.log(v))
There are two points that I haven't been able to clarify:
1 - I don't know if I am using Gun sets well: I tried to add some relationships but didn't work out; consider the following instructions:
macDoland.get('client').put(rootNode)
frankMirrors.get('client').put(rootNode)
I tried to put a client relationship for both customer nodes, but printing rootNode showed me that rootNode had client relationship only with frankMirrors node! The first relationship with macDoland node disappeared so I started using Gun sets.
My code works (more or less) but I don't know if I am using Gun set properly and if this is the right way to do it, given the kind of relationship I want to build between main vendors, customers, customers' branches and sensors in each branch.
2 - I'd like to make this approach more generic and scalable: for now there are clients, branches and sensors; this may change in future and the number of levels between clients and sensors may increase.
This means that there may be an arbitrary number of levels between client nodes (depth 1) and sensors (max depth): for example, a very small client may be without branches and thus its client node smallCompany would directly be linked to its sensors; for another example, a gigantic client may have (say) five level of depths and I don't want to hard-code Gun set names such as macDolandNySubSubSubSubBranch.
How could I provide scalability for an arbitrary number of sub-branches?

Javascript seperate value from array

I have this,
[{"cart_id":"5BqDu","product":[{"id":1,"qty":"11","name":"test product","pv":"100","price":"23","sub_price":253,"sub_pv":1100},{"id":2,"qty":"11","name":"test product 2","pv":"null","price":"11","sub_price":121,"sub_pv":null}],"shipping":{"member_id":"00000000","member_pass":"0987654321","receiver":"asasdsdasd123","full_address":"Taman ABC Lorong ccc Bagan Gajar, 11100 Pulau pINANG.","postcode":"21313213","country":"malaysia","phone_no":"321312"}},{"cart_id":"xEopa","product":[{"id":2,"qty":"1","name":"test product 2","pv":"null","price":"11","sub_price":11,"sub_pv":null}],"shipping":{"member_id":"09876543","member_pass":"11232312","receiver":"sdasdsadas","full_address":"adsadzcfdhg43324","postcode":"12323","country":"malaysia","phone_no":"321312"}},{"cart_id":"0WyEm","product":[{"id":2,"qty":"5","name":"test product 2","pv":"null","price":"11","sub_price":55,"sub_pv":null},{"id":1,"qty":"3","name":"test product","pv":"100","price":"23","sub_price":69,"sub_pv":300}],"shipping":{"member_id":"12345678","member_pass":"0987654321","receiver":"MR ABCDEF","full_address":"NO. 123, LORONG ABC, TAMAN AMAN CCC, BAGAN AJAM, 11100 KUALA LUMPUR, MALAYSIA.","postcode":"123453","country":"MALAYSIA","phone_no":"0123456789"}},{"cart_id":"ox9IK","product":[{"id":1,"qty":"2","name":"test product","pv":"100","price":"23","sub_price":46,"sub_pv":200},{"id":2,"qty":"5","name":"test product 2","pv":"null","price":"11","sub_price":55,"sub_pv":null}],"shipping":""},{"cart_id":"jz2j2","product":[{"id":1,"qty":"1","name":"test product","pv":"100","price":"23","sub_price":23,"sub_pv":100},{"id":2,"qty":"4","name":"test product 2","pv":"null","price":"11","sub_price":44,"sub_pv":null}],"shipping":""},{"cart_id":"6eE0x","product":[{"id":1,"qty":"1","name":"test product","pv":"100","price":"23","sub_price":23,"sub_pv":100}],"shipping":{"member_id":"S4567890","member_pass":"atomy123","receiver":"Siew","full_address":"56, Jalan Emas 8, Taman Bukit Beruang.","postcode":"75750","country":"Malaysia","phone_no":"0198907654"}},{"cart_id":"iRw6b","product":[{"id":2,"qty":"1","name":"test product 2","pv":"null","price":"11","sub_price":11,"sub_pv":null}],"shipping":{"member_id":"12345670","member_pass":"121334","receiver":"sdfsdaf","full_address":"sgdfgdfs","postcode":"12341","country":"Malaysia","phone_no":"0192321008"}},{"cart_id":"bbKf9","product":[{"id":2,"qty":"1","name":"test product 2","pv":"null","price":"11","sub_price":11,"sub_pv":null}],"shipping":{"member_id":"S6789212","member_pass":"12345678","receiver":"Mary","full_address":"Taman Tasik Utama","postcode":"12233","country":"Malaysia","phone_no":"0197321830"}},{"cart_id":"B1DLq","product":[{"id":2,"qty":"5","name":"test product 2","pv":"null","price":"11","sub_price":55,"sub_pv":null},{"id":1,"qty":"1","name":"test product","pv":"100","price":"23","sub_price":23,"sub_pv":100}],"shipping":{"member_id":"09876556","member_pass":"hijk","receiver":"sim","full_address":"Taman Tasik Utama","postcode":"12233","country":"Malaysia","phone_no":"0987654321"}}]
I only need product id from all
What can I do ?
Try this:
let carts = / * the data you posted above */
let ids = [];
carts.forEach(cart => {
const products = cart.product;
products.forEach(product => {
ids.push(product.id);
});
});
Note that there are no check that handles a missing if property so you might want to add that.

Updating time and date in wit-ai weather example

I am trying to extend the wit-ai weather example by adding wit/datetime to the mix.
For example a user might type "How cold will it be in Berlin in 1 hour?" and the weather bot will bring back the data for the weather in 1 hour in Berlin.
So far this works, but when I try to setup missingDate in order to ask the date if it's missing it behaves kind of funny.
A dialogue would be:
- How cold will it be in Berlin?
- In what time?
- In 1 hour.
Instead, after the 1 hour step, I get asked again for the location which is in the context, but instead is triggered again.
My action is named getForecast({context, entities}) and I have defined it as below:
actions:
[...],
getForecast({ context, entities }) {
console.log(`The current context is: ${JSON.stringify(context)}`);
console.log(`Wit extracted ${JSON.stringify(entities)}`);
// extract entity
var location = firstEntityValue(entities, "location");
var date = firstEntityValue(entities, "datetime");
// if the entity exists, do a remote weather call.
if (date) {
context.date = date;
delete context.missingDate;
} else {
context.missingDate = true;
delete context.date;
delete context.forecast;
}
if (location) {
context.forecast = '38 degrees';
context.location = location;
delete context.missingLocation;
} else {
context.missingLocation = true;
delete context.forecast;
}
// return the context object
return Promise.resolve(context);
}

Relate/link vendor bill to purchase order in Netsuite

I have created vendor bill with nlapiCreateRecord, I can see the Bill record in the system with all items I want, but I can't relate it / link it to specific Purchase Order natively. When I'm using nlapiTransformRecord I'm deleting all records first from the PO and I'm adding new line items from CSV, but the native link/relationship between PO and Vendor Bill is missing. Here is my code created for the Bill Import from CSV:
function BillImport() {
var fromrecord;
var fromid;
var torecord;
var record;
var qty;
fromrecord = 'purchaseorder';
fromid = 23664;
torecord = 'vendorbill';
var loadedBillFile = nlapiLoadFile(5034);
var loadedBillString = loadedBillFile.getValue();
var BillLines = loadedBillString.split('\r\n'); //split on newlines
record = nlapiTransformRecord(fromrecord, fromid, torecord);
//trecord.setFieldValue('location', 1);
//trecord.setFieldValue('tranid', 'TEST!');
//var record = nlapiCreateRecord('vendorbill');
for (var j = record.getLineItemCount('item'); j>=1; j--)
{
record.removeLineItem('item',j);
}
for (var i = 1; i < BillLines.length; i++) {
var cols = BillLines[i].split(';');
var dsplit = cols[4].split(".");
var date = new Date(dsplit[2],dsplit[1],dsplit[0]);
currentDate = date.getMonth() + '/' + date.getDate() + '/' + date.getFullYear();
var entity = cols[0]; // OK HEAD
var currency = cols[1]; // OK LINE
var taxcode = cols[2]; // SKIP
var tranid = cols[3]; // OK HEAD
var trandate = currentDate; // OK HEAD FORMAT 11/3/2016
var location = 21;//cols[5]; // OK HEAD (ID of Location)
var item = cols[6]; // OK LINE
var quantity = cols[7];
var rate = parseFloat(cols[8]); // FLOAT
var amount = parseFloat(cols[9]);
var po = cols[10];
record.selectNewLineItem('item');
// Head Level
record.setFieldValue('createdfromstatus','');
record.setFieldValue('entity', entity);
record.setFieldValue('tranid', tranid);
record.setFieldValue('trandate', trandate);
record.setFieldValue('location', location);
// Line Level
record.setCurrentLineItemValue('item','item', item);
record.setCurrentLineItemValue('item','quantity', quantity);
record.setCurrentLineItemValue('item','rate', rate);
record.setCurrentLineItemValue('item','amount', amount);
//record.setCurrentLineItemValue('item','orderdoc', po);
//record.setCurrentLineItemValue('item','podocnum', po);
record.commitLineItem('item');
}
var id = nlapiSubmitRecord(record, true);
//trecord.setLineItemValue('item', 'amount', 1, 3 );
//var idl = nlapiSubmitRecord(trecord, true);
}
Here is the example CSV file:
Entity;Currency;Taxcode;Tranid;TranDate;Location;Item;Quantity;Rate;Amount;PO Internal ID
2449;USD;0.00 ;224676;11.3.2016;21;885;1;10;50;23664
2449;USD;0.00 ;224676;11.3.2016;21;870;2;10;120;23664
2449;USD;0.00 ;224676;11.3.2016;21;890;3;3;45;23664
2449;USD;0.00 ;224676;11.3.2016;21;948;4;4,66;38,5;23664
2449;USD;0.00 ;224676;11.3.2016;21;886;5;19,54;720;23664
I'm
If you don't want it to transform into a Vendor Bill (probably to avoid the PO from changing status) then you will need to create a custom relationship. You do this by:
Create a custom field on the Vendor Bill form of type "List/Record" and have the it be of "Transaction" type and check "Record is Parent". Save the Custom Field.
Go back to the custom field and edit it. Go to the display tab and select a "Parent Subtab", I usually select "Related Records". Save.
Now you just need to create a new Vendor Bill from scratch and save the record id of the PO in the Vendor Bill using the new custom field. Leave the "Created From" field blank, otherwise you would be linking them natively. The Bill should be listed under the "Related Records" tab or whichever subtab you selected on the PO.
Vendor bill import via CSV method is doable but you can bill the Purchase Order completely and not partially i.e. if you try to import a bill mentioning any referenced Purchase Order's link in it, it'll create a bill for all the remaining unbilled quantities of the Purchase Order rather than the quantity you have mentioned.
Actually if you mention any quantity AND Purchase Order link BOTH in the CSV file then it will throw an error.
Below is the part I found from the SuiteAnswers with answer id as 10020.
Refer the supporting image here

Resources