Swift Repeat Interval - uisegmentedcontrol

I have an app I'm working on with a UISegmentedControl to allow the user to select a repeat interval for the notification they are creating. They also pick the date and time to start, by selecting it on the UIDatePicker.
//Variables for Repeat (SegmentedControl)
var hourly = true
var daily = true
//Outlets
#IBOutlet weak var titleField: UITextField!
#IBOutlet weak var deadlinePicker: UIDatePicker!
#IBOutlet weak var repeatPreseto: UISegmentedControl!
#IBOutlet weak var saveButtonOutlet: UIButton!
//Repeat Segmented Control
#IBAction func repeatPreset(sender: UISegmentedControl) {
var index = sender.selectedSegmentIndex
hourly = index == 0
daily = index == 2
if hourly {
notification.repeatInterval = NSCalendarUnit.CalendarUnitHour
}
if daily {
notification.repeatInterval = NSCalendarUnit.CalendarUnitDay
}
}
Right now the hourly and daily repeatInterval is working great.
I've looked online and can't find anything to allow for the user to set the repeatInterval for certain days of the week.

I found out that one of the old interval methods was depreciate in iOS 8.0. I found I need to use:
notification.repeatInterval = NSCalendarUnit.CalendarUnitWeekOfMonth

Related

billing schedule record creation on netsuite

I have written a script which creates a billing schedule record for items on the creation of sales order using afterSubmit() user event script.
The billing schedule record gets created for every item,but it also should be set in line level field 'billing schedule' of the sales order.details in attachment
var rec =nlapiCreateRecord('billingschedule');
var res = itemname.substring(0, 40);
rec.setFieldValue('name',res);
rec.setFieldValue('initialamount',itemamount);
rec.setFieldValue('numberremaining','5');
rec.setFieldText('frequency','Daily');
var sub = nlapiSubmitRecord(rec,true);
if(sub!=null)
{
nlapiSetLineItemValue('item','billingschedule',i+1,sub);
}
You need to load the record in afterSubmit, otherwise it's read-only.
var salesOrderId = nlapiGetRecordId();
var soRec = nlapiLoadRecord('salesorder', salesOrderId);
// DO YOUR BILLING SCHEDULE CREATION LINE WORK
var soLines = soRec.getLineItemCount('item');
// SS1 indexes start at 1
for (var x = 1; x <= soLines; x++) {
var rec =nlapiCreateRecord('billingschedule');
var res = itemname.substring(0, 40);
rec.setFieldValue('name',res);
rec.setFieldValue('initialamount',itemamount);
rec.setFieldValue('numberremaining','5');
rec.setFieldText('frequency','Daily');
var sub = nlapiSubmitRecord(rec,true);
if(sub!=null) {
soRec.setLineItemValue('item','billingschedule', x, sub);
}
}
// Submit the record to save the values
nlapiSubmitRecord(soRec);

Netsuite Past Due Reminder using SuiteScript

The script is complete! Thanks for all those who replied :)
/*
* Author: Laura Micek
* Date: 5-13-15
* Purpose: This script creates a saved search in order to pull the information needed to send out an email to alert customers that
* their account is past due. The saved searched makes sure that the customer is 11 days or more past due, checks to see if they are
* exempt from past due reminders, and that their account balance is greater than 1. Once the saved search runs, it will loop thru the
* customers that meet these requirements and it will use the days past due to determine if an email needs to be sent. An email will
* only be sent if the days past due are equal to 11 or if the days past due minus 11, modded by 8 equals 0 which means that it has
* been 8 days since the last notification.
*/
function email_late_customers(type) {
//variables
var send_from = 22730; // Internal ID of NS User
//setup filters and result columns for a customer saved search
var filters = new Array();
filters[0] = new nlobjSearchFilter('daysoverdue',null,'greaterthanorequalto',11);
filters[1] = new nlobjSearchFilter('custentitypastdueremind',null,'is', 'F');
filters[2] = new nlobjSearchFilter('balance',null,'greaterthan', 1);
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid');
columns[1] = new nlobjSearchColumn('email');
columns[2] = new nlobjSearchColumn('daysoverdue');
//run saved search and loop thru results
var customers = nlapiSearchRecord('customer',null,filters,columns);
for (var i = 0; customers != null && i < customers.length; i++) {
//grab all the customer data
var this_customer = customers[i];
var cust_id = this_customer.getValue('internalid');
var send_to = this_customer.getValue('email');
var getpastduedays = this_customer.getValue('daysoverdue');
//this is the check to see if the amount of days is over 11 to see if another email needs to be sent.
if(getpastduedays > 11) {
var checkPastDue = (getpastduedays - 11) % 8;
}
/*
if the above checkPastDues evaluates to zero then it has been 8 days since the last notification, this is the other condition to send an email. The first being that the customer is 11 days past due.
*/
if(getpastduedays == 11 || checkPastDue == 0) {
//email subject
var subject = 'Your Account is Past Due';
// create body text
var body = 'Hello, \r\r';
body += ' This is a reminder that your account is currently past due. Attached is a current detailed aging of your account for your reference.\r\r ';
body += ' Can you please review and let me know the status of payment?\r\r';
body += ' Your prompt attention to this matter would be greatly appreciated. If you have any questions reguarding this account, please ';
body += ' contact us as soon as possible. Any questions or invoice copy requests can be email to ar#doubleradius.com.\r\r';
body += ' If payment has been recently been made, please accept our thanks and ignore this reminder.\r\r';
body += 'Thank You!\r\r';
//setup filters and result columns for a transaction saved search
var filters = new Array();
filters[0] = new nlobjSearchFilter('status',null,'is', 'CustInvc:A');
filters[1] = new nlobjSearchFilter('type',null,'is', 'CustInvc');
filters[2] = new nlobjSearchFilter('email',null,'is', send_to);
filters[3] = new nlobjSearchFilter('mainline',null,'is', 'T');
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid');
//run saved search and loop thru results
var transactions = nlapiSearchRecord('transaction',null,filters,columns);
var invoices = [];
for (var i = 0; transactions != null && i < transactions.length; i++) {
//grab all the transaction data
var this_transaction = transactions[i];
invoices[i] = this_transaction.getValue('internalid');
}
//print the statement to a PDF file object
var attachment = [];
for (var i = 0; invoices != null && i < invoices.length; i++) {
attachment[i] = nlapiPrintRecord('TRANSACTION',invoices[i],'DEFAULT',null);
}
//send the PDF as an attachment
nlapiSendEmail(send_from,/*send_to*/ 'lauram#doubleradius.com', subject, body, null, null, null, attachment);
}
}
}
You don't need scripting to achieve this simple requirement. All you need is a saved search and a workflow. The key thing here is you need to come up with the right criteria on your saved search. Once you have the right saved search you set your workflow's Initiation to run on Scheduled and choose the frequency. Use the Send Email action to send the email to the customers and you are good to go.
Also, from the saved search you can join the customer record to the Messages Field so you will have the ability to check when was the last email sent.
You might also need a Email Template.
If you're going to use a Scheduled Script you will need to collect the records you want to inspect. If these are Customer records then be sure to setup searchFilters and searchColumns to come back and then collect the results.
// set Customer record filters and columns to return
var filters = new Array();
filters.push( new nlobjSearchFilter('isActive', null, 'is', 'F') );
filters.push( new nlobjSearchFilter('someotherfield', null, 'isempty') );
var cust_cols = new Array();
cust_cols.push( new nlobjSearchColumn('companyname') );
cust_cols.push( new nlobjSearchColumn('someotherfield') );
// now get the records that fit your filters and return the cols specified
overdue_customers = nlapiSearchRecord('customer', null, searchfilter, columns);
I generally like to move my content/body creating code into separate functions but it's really not that important depending on how complicated your script is. For instance I have a couple of scripts that do a lot of processing that have to send some information on a record by record basis but also sends "digest" type emails to others. Think customers and account managers. While it was a pain to set up everything up to handle both cases having a email content generating function was much saner and easier to read.
Though there are many approaches you could use for this, I think your scheduled script approach will work just fine. You can make the logic for identifying which emails to send by offloading the 8-day calculation to your search filters, instead of manually trying to compute. I would have a filter in my search of something like:
new nlobjSearchFilter('custentity_dayssincelastemailed', null, 'before', 'previousOneWeek');
See the Help article titled Search Date Filters for more details on what you can do with Dates in filters.
After that, I believe you should be able to create an Email Template and utilize that in your code to set the title and the boilerplate of the email body.
Where I'm a little less certain, and what may be more difficult for you, is your A/R Aging attachment. Not sure I've worked with attaching statements.

populate a button from coredata

I’m spending lots of time trying to figure this out and getting no where.
I have an entity with a NSDate attribute, which successfully saves.
How on Earth do I fetch the NSDate from the store(year only section) and make it populate the text on a button.
so the button can be pressed later and taken to another View Controller/Table View Controller.
I have spent hours trying to figure this out, I’m totally stuck can’t find any examples.
Does anyone have the time to help with this please.
Using Swift
(hopefully I have formated this question correctly, bit of a noob here)
Thank you for looking
//year button
#IBAction func btnYear(sender: AnyObject) {
//APP DEL REFERANCE
var appdel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context: NSManagedObjectContext = appdel.managedObjectContext!
let ent = NSEntityDescription.entityForName("FilmInfo", inManagedObjectContext: context)!
// fetch request
var request = NSFetchRequest(entityName: "FilmInfo")
request.returnsObjectsAsFaults = false
First, get the date from your data.
object.date
Then, format it so you can display it on the button.
var formatter = NSDateFormatter()
formatter.dateStyle= .ShortStyle
let buttonTitle = formatter.stringFromDate(object.date)
Finally assign the title to the button
button.setTitle(buttonTitle, forState: .Normal)
To get to the object in the first place, fetch it. Don't forget to execute your fetch request.
var request = NSFetchRequest(entityName: "FilmInfo")
request.predicate = NSPredicate(format:"id = %#", aFilmInfoID) // example
request.fetchLimit = 1
let results = context.executeFetchRequest(request, error:nil)! as [FilmInfo]
let object = results.first!
You need to execute your fetch request in your context.
var resultsArray = context.executeFetchRequest(request,nil)
if let arr = resultsArray {
//we have some results
var firstObject: FilmInfo = arr[0] as FilmInfo
var date = firstObject.date
}
If you are interested in only one object you can always set request.fetchLimit = 1
Getting more advanced you can also fetch only the date property:
fetch.propertiesToFetch = ["date"]
fetch.resultType = .DictionaryResultType

Google Apps Script - Exporting events from Google Sheets to Google Calendar - how can I stop it from removing my spreadsheet formulas?

I've been trying to create a code that takes info from a Google Spreadsheet, and creates Google Calendar events. I'm new to this, so bear with my lack of in-depth coding knowledge!
I initially used this post to create a code:
Create Google Calendar Events from Spreadsheet but prevent duplicates
I then worked out that it was timing out due to the number of rows on the spreadsheet, and wasn't creating eventIDs to avoid the duplicates. I got an answer here to work that out!
Google Script that creates Google Calendar events from a Google Spreadsheet - "Exceeded maximum execution time"
And now I've realised that it's over-writing the formulas, I have in the spreadsheet, auto-completing into each row, as follows:
Row 12 - =if(E4="","",E4+1) // Row 13 - =if(C4="","",C4+1) // Row 18 - =if(B4="","","WHC - "&B4) // Row 19 - =if(B4="","","Docs - "&B4)
Does anyone have any idea how I can stop it doing this?
/**
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the exportEvents() function.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export WHCs",
functionName : "exportWHCs"
},
{
name : "Export Docs",
functionName : "exportDocs"
}];
sheet.addMenu("Calendar Actions", entries);
};
/**
* Export events from spreadsheet to calendar
*/
function exportWHCs() {
// check if the script runs for the first time or not,
// if so, create the trigger and PropertiesService.getScriptProperties() the script will use
// a start index and a total counter for processed items
// else continue the task
if(PropertiesService.getScriptProperties().getKeys().length==0){
PropertiesService.getScriptProperties().setProperties({'itemsprocessed':0});
ScriptApp.newTrigger('exportWHCs').timeBased().everyMinutes(5).create();
}
// initialize all variables when we start a new task, "notFinished" is the main loop condition
var itemsProcessed = Number(PropertiesService.getScriptProperties().getProperty('itemsprocessed'));
var startTime = new Date().getTime();
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 4; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
var calId = "flightcentre.com.au_pma5g2rd5cft4lird345j7pke8#group.calendar.google.com";
var cal = CalendarApp.getCalendarById(calId);
for (i in data) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[12]); // First column
var title = row[18]; // Second column
var tstart = new Date(row[15]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[16]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var id = row[17]; // Sixth column == eventId
// Check if event already exists, update it if it does
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"));
var newEvent = cal.createEvent(title, tstart, tstop).addEmailReminder(5).getId();
row[17] = newEvent; // Update the data array with event ID
}
else {
event.setTitle(title);
}
if(new Date().getTime()-startTime > 240000){ // if > 4 minutes
var processed = i+1;// save usefull variable
PropertiesService.getScriptProperties().setProperties({'itemsprocessed':processed});
range.setValues(data);
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),'progress sheet to cal','item processed : '+processed);
return;
}
debugger;
}
// Record all event IDs to spreadsheet
range.setValues(data);
}
/**
* Export events from spreadsheet to calendar
*/
function exportDocs() {
// check if the script runs for the first time or not,
// if so, create the trigger and PropertiesService.getScriptProperties() the script will use
// a start index and a total counter for processed items
// else continue the task
if(PropertiesService.getScriptProperties().getKeys().length==0){
PropertiesService.getScriptProperties().setProperties({'itemsprocessed':0});
ScriptApp.newTrigger('exportDocs').timeBased().everyMinutes(5).create();
}
// initialize all variables when we start a new task, "notFinished" is the main loop condition
var itemsProcessed = Number(PropertiesService.getScriptProperties().getProperty('itemsprocessed'));
var startTime = new Date().getTime();
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 4; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
var calId = "flightcentre.com.au_pma5g2rd5cft4lird345j7pke8#group.calendar.google.com";
var cal = CalendarApp.getCalendarById(calId);
for (i in data) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[13]); // First column
var title = row[19]; // Second column
var tstart = new Date(row[15]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[16]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var id = row[20]; // Sixth column == eventId
// Check if event already exists, update it if it does
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"));
var newEvent = cal.createEvent(title, tstart, tstop).addEmailReminder(5).getId();
row[20] = newEvent; // Update the data array with event ID
}
else {
event.setTitle(title);
}
if(new Date().getTime()-startTime > 240000){ // if > 4 minutes
var processed = i+1;// save usefull variable
PropertiesService.getScriptProperties().setProperties({'itemsprocessed':processed});
range.setValues(data);
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),'progress sheet to cal','item processed : '+processed);
return;
}
debugger;
}
// Record all event IDs to spreadsheet
range.setValues(data);
}
You have to ways to solve that problem.
First possibility : update your sheet with array data only on columns that have no formulas, proceeding as in this other post but in your case (with multiple columns to skip) it will rapidly become tricky
Second possibility : (the one I would personally choose because I 'm not a "formula fan") is to do what your formulas do in the script itself, ie translate the formulas into array level operations.
following your example =if(E4="","",E4+1) would become something like data[n][4]=data[n][4]==''?'':data[n+1][4]; if I understood the logic (but I'm not so sure...).
EDIT
There is actually a third solution that is even simpler (go figure why I didn't think about it in the first place...) You could save the ranges that have formulas, for example if col M has formulas you want to keep use :
var formulM = sheet.getRange('G1:G').getFormulas();
and then, at the end of the function (after the global setValues()) rewrite the formulas using :
sheet.getRange('G1:G').setFormulas(formulM);
to restore all the previous formulas... as simple as that, repeat for every column where you need to keep the formulas.

Creating spam filter for Gmail

I am so sick of getting unwanted mails in my gmail inbox that I am now willing to create a white-list kind of extension which filters all mails coming from people who are not in my contacts list. I searched for this many hours but could not find anything hence thinking of doing this exercise (if it exists, please share the link). I have created 100's of filters but definitely spammers outpace me everytime.
Can someone tell me whether this is possible in first place? I have seen extensions which add functionality in gmail but I don't know how to block an email through an extension. Plz help.
You can setup a whitelist in Gmail but it is unlikely to work for such a large list of addresses. What you can do is create a Google sheet with a list of valid addresses and a Google Script that will scan your inbox against these addresses.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getDataRange();
var values = range.getValues();
var emails = [];
for (var i in values) {
emails.push(values[i][0]);
}
var threads = GmailApp.search("in:inbox is:unread");
for (var i=0; i<threads.length; i++) {
var from = threads[i].getMessages()[0].getFrom();
if ( !emails.indexOf(from) ) {
threads[i].moveToSpam();
}
}
You need to setup a trigger that runs this script every 5 minutes or so.
Thanks a lot Amit for sharing this snippet. With the help of this, I was able to come up with a working solution (ver1.0) and sharing below for others:
function createTriggers() {
ScriptApp.newTrigger('runSpamFilter').timeBased().everyMinutes(10).create();
SpreadsheetApp.getActiveSpreadsheet().toast("The program will check for spam email every 10 minutes and"
+ " send them to Spam Folder after applying label MySpam. You may please close this window.", "Initialized");
}
function removeTriggers(show) {
var triggers = ScriptApp.getScriptTriggers();
for (i=0; i<triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
if (show) {
SpreadsheetApp.getActiveSpreadsheet().toast("The program has stopped.", "Uninstalled");
}
}
function runSpamFilter() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getDataRange();
var values = range.getValues();
var emails = [];
var regex = /([a-zA-Z0-9+._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi;
var my_label = GmailApp.getUserLabelByName("MySpam");
var spamCount = 0;
for (var i in values) {
emails.push(values[i][0]);
}
var threads = GmailApp.search("in:inbox is:unread");
for (var i=0; i<threads.length; i++) {
var from = threads[i].getMessages()[0].getFrom();
var from_email = from.match(regex);
if ( emails.indexOf(from_email[0]) == -1 ) {
threads[i].addLabel(my_label);
threads[i].moveToSpam();
spamCount++;
}
}
Logger.log("Spams found = %s", spamCount);
}
function startProgram() {
removeTriggers(false);
createTriggers();
}
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var menu = [
{name: "Step 1: Initialize", functionName: "startProgram"},
{name: "Step 2: Start ", functionName: "runSpamFilter"},
{name: "Uninstall (Stop)", functionName: "removeTriggers"}
];
sheet.addMenu("Gmail Spam Filter v1.0", menu);
}
I may also come up with ver2.0 which removes the current limitation of this script. As of now, you have to make a spreadsheet having all your contacts email addresses. But once you add a new contact, this spreadsheet needs to be updated manually. Hence this script needs an additional trigger which would update the spreadsheet once in say 15 days with the recently added contacts/email addresses. I will share that too later or may be someone can pick from here and come up with ver2.0.
Thanks again.

Resources