-
-
Save jeffleeismyhero/8b3486f37d4ed7b0a60c to your computer and use it in GitHub Desktop.
Zebra ZQ510 Print Job
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "VPDeviceDelegate.h" | |
#import "AFNetworking.h" | |
#import "VPConstants.h" | |
// Zebra Printers | |
#import "ZebraPrinter.h" | |
#import "ZebraPrinterFactory.h" | |
#import "ZebraPrinterConnection.h" | |
#import "MfiBtPrinterConnection.h" | |
#import "PrinterStatus.h" | |
#import "SGD.h" | |
#import <ExternalAccessory/ExternalAccessory.h> | |
#import "AppDelegate.h" | |
#define VP_APPDELEGATE ((AppDelegate *)[UIApplication sharedApplication].delegate) | |
@implementation VPDevices | |
@synthesize delegate; | |
- (id)init { | |
self = [super init]; | |
[[NSNotificationCenter defaultCenter] addObserver:self | |
selector:@selector(accessoryDidConnect:) | |
name:EAAccessoryDidConnectNotification | |
object:nil]; | |
[[NSNotificationCenter defaultCenter] addObserver:self | |
selector:@selector(accessoryDidDisconnect:) | |
name:EAAccessoryDidDisconnectNotification | |
object:nil]; | |
[[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications]; //we want to hear about accessories connecting and disconnecting | |
return self; | |
} | |
- (void)dealloc { | |
[[NSNotificationCenter defaultCenter] removeObserver:self name:EAAccessoryDidDisconnectNotification object:nil]; | |
[[NSNotificationCenter defaultCenter] removeObserver:self name:EAAccessoryDidConnectNotification object:nil]; | |
[[EAAccessoryManager sharedAccessoryManager] unregisterForLocalNotifications]; | |
} | |
- (void)deviceSelection { | |
EAAccessoryManager *accessoryManager = [EAAccessoryManager sharedAccessoryManager]; | |
NSLog(@"Connected: %@", [accessoryManager connectedAccessories]); | |
[accessoryManager showBluetoothAccessoryPickerWithNameFilter:nil completion:^(NSError * _Nullable error) { | |
NSLog(@"Finished selection of accessory."); | |
}]; | |
} | |
#pragma mark - Printer | |
// Determines which type(s) of printer is connected | |
- (NSString *)connectedPrinterType { | |
NSString *printerType = @""; | |
if ([self zebraPrinterStatus]) { | |
printerType = [NSString stringWithFormat:@"%@%@", printerType, @"[ZEBRA]"]; | |
} | |
return printerType; | |
} | |
/* | |
// The methods that generate this data should be pulled out into another class | |
*/ | |
- (BOOL)printReceipt:(Order *)order { | |
NSLog(@"Printing receipt..."); | |
NSError *error = nil; | |
if ([[self connectedPrinterType] isEqualToString:@"[ZEBRA]"]) { | |
__block BOOL status = NO; | |
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; | |
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"]; | |
// Dispatch this task to the default queue | |
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ { | |
// Instantiate connection to Zebra Bluetooth accessory | |
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber]; | |
// Open the connection - physical connection is established here. | |
[connection open]; | |
status = [connection isConnected]; | |
if (status) { | |
NSError *error = nil; | |
[SGD SET:@"device.languages" withValue:@"zpl" andWithPrinterConnection:connection error:&error]; | |
NSLog(@"ZEBRA: Language error: %@", error); | |
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error]; | |
NSLog(@"ZEBRA: Connection error: %@", error); | |
// Store the logo image on the printer | |
UIImage *logoImage = [UIImage imageNamed:@"logo-v5.png"]; | |
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil]; | |
[graphicsUtil storeImage:@"LOGO_V5" withImage:[logoImage CGImage] withWidth:logoImage.size.width andWithHeight:logoImage.size.height error:&error]; | |
NSLog(@"ZEBRA: Graphics error: %@", error); | |
// Spacing and length | |
int leftSpacing; | |
long length = 0; | |
NSString *padding; | |
// Start of print | |
NSString *printString = @"^XA^POI^PW576^MNN^LL%d^LH0,0"; | |
// Start off with 10 dots of padding | |
length += 10; | |
NSString *imageName = @"LOGO_V5"; | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, imageName]; | |
length += 150; | |
// Receipt Header | |
NSString *header = @"RECEIPT ONLY"; | |
leftSpacing = ceil((18 - [header length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
header = [padding stringByAppendingString:header]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,24,24^FO30,%ld^FD%@^FS", printString, length, header]; | |
// This portion is approximately 60 dots | |
length += 60; | |
// Terminal and Date line | |
// Terminal Number | |
NSString *terminalNumber = [NSString stringWithFormat:@"TERMINAL %03d", [[order valueForKey:@"deviceID"] intValue]]; | |
// Order Date | |
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; | |
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; | |
[dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss a"]; | |
NSString *dateString = [dateFormatter stringFromDate:order.completedAt]; | |
NSString *terminalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@ %@^FS", length, terminalNumber, dateString]; | |
printString = [printString stringByAppendingString:terminalString]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Order Number line | |
NSString *orderNumberString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FDOrder Number: %@^FS", length, order.orderNumber]; | |
printString = [printString stringByAppendingString:orderNumberString]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Line Items | |
NSArray *lineItems = [NSKeyedUnarchiver unarchiveObjectWithData:order.lineItems]; | |
for (id lineItem in lineItems) { | |
NSDictionary *line = [lineItem objectForKey:@"line_item"]; | |
NSString *ticketLabel = [line objectForKey:@"ticket_label"]; | |
NSString *quantity = [[line objectForKey:@"quantity"] stringValue]; | |
NSString *price = [line objectForKey:@"price"]; | |
NSString *unadjustedLineTotal = [line objectForKey:@"unadjusted_line_total"]; | |
NSString *product = [NSString stringWithFormat:@"%@ (%@ @ %@)", ticketLabel, quantity, price]; | |
product = [product stringByPaddingToLength:(45 - [unadjustedLineTotal length]) withString:@" " startingAtIndex:0]; | |
// Order Line Items | |
NSString *lineItemString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, product, unadjustedLineTotal]; | |
printString = [printString stringByAppendingString:lineItemString]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Order Discounts | |
NSArray *adjustments = [NSKeyedUnarchiver unarchiveObjectWithData:order.adjustments]; | |
NSArray *discounts = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Discount"]; | |
}]]; | |
NSArray *comps = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Comp"]; | |
}]]; | |
NSArray *wholesalers = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Wholesaler"]; | |
}]]; | |
NSArray *concierges = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Concierge"]; | |
}]]; | |
if ([discounts count] > 0) { | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
NSString *discountTotal = [@"Discount Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0]; | |
// Discount Total | |
NSString *discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, discountTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:discountTotalString]; | |
discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, discountTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:discountTotalString]; // Creates a bold effect | |
discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, discountTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:discountTotalString]; // Creates a bold effect | |
// This portion is approximately 25 dots | |
length += 25; | |
for (id discount in discounts) { | |
id discountObject = [discount objectForKey:@"adjustment"]; | |
NSDictionary *discountLabel = [discountObject objectForKey:@"label"]; | |
NSString *discountQuantity = [discountObject objectForKey:@"quantity"]; | |
NSString *discountUnitAmount = [discountObject objectForKey:@"formatted_unit_amount"]; | |
NSString *discountAmount = [discountObject objectForKey:@"formatted_total_amount"]; | |
NSString *discountString = [NSString stringWithFormat:@" %@ (%@ @ %@)", discountLabel, discountQuantity, discountUnitAmount]; | |
discountString = [discountString stringByPaddingToLength:(45 - [discountAmount length]) withString:@" " startingAtIndex:0]; | |
NSString *discountLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, discountString, discountAmount]; | |
printString = [printString stringByAppendingString:discountLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
} else if ([comps count] > 0) { | |
NSString *compTotal = [@"Comp Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, compTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:compLine]; | |
compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, compTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:compLine]; | |
compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, compTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:compLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} else if ([wholesalers count] > 0) { | |
NSString *wholesaleTotal = [@"Wholesale Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *wholesaleLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, wholesaleTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:wholesaleLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} else if ([concierges count] > 0) { | |
NSString *conciergeTotal = [@"Concierge Deposit:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, conciergeTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:conciergeLine]; | |
conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, conciergeTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:conciergeLine]; | |
conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, conciergeTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:conciergeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Total Line | |
NSString *total = [@"TOTAL" stringByPaddingToLength:(45 - [order.orderTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, total, order.orderTotal]; | |
printString = [printString stringByAppendingString:totalLine]; | |
totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, total, order.orderTotal]; | |
printString = [printString stringByAppendingString:totalLine]; | |
totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, total, order.orderTotal]; | |
printString = [printString stringByAppendingString:totalLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Payment Detail | |
NSArray *transactions = [NSKeyedUnarchiver unarchiveObjectWithData:order.transactions]; | |
for (id transaction in transactions) { | |
NSDictionary *payment = [transaction objectForKey:@"transaction"]; | |
NSString *gatewayTransactionID = [payment objectForKey:@"gateway_transaction_id"]; | |
NSString *cardType = [payment objectForKey:@"card_type"]; | |
NSString *cardNumber = [payment objectForKey:@"last_digits"]; | |
NSString *cardTypeString = [[cardType uppercaseString] stringByPaddingToLength:(45 - [order.amountTendered length]) withString:@" " startingAtIndex:0]; | |
NSString *cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, cardTypeString, order.amountTendered]; | |
printString = [printString stringByAppendingString:cardTypeLine]; | |
cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, cardTypeString, order.amountTendered]; | |
printString = [printString stringByAppendingString:cardTypeLine]; | |
cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, cardTypeString, order.amountTendered]; | |
printString = [printString stringByAppendingString:cardTypeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
if ([cardNumber length] > 0) { | |
NSString *cardNumberString = [@" Card Number (last 4):" stringByPaddingToLength:(45 - [cardNumber length]) withString:@" " startingAtIndex:0]; | |
NSString *cardNumberLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, cardNumberString, cardNumber]; | |
printString = [printString stringByAppendingString:cardNumberLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
NSString *responseCodeString = [@" Transaction ID:" stringByPaddingToLength:(45 - [gatewayTransactionID length]) withString:@" " startingAtIndex:0]; | |
NSString *responseCodeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, responseCodeString, gatewayTransactionID]; | |
printString = [printString stringByAppendingString:responseCodeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
NSString *change = [@"CHANGE:" stringByPaddingToLength:(45 - [order.changeDue length]) withString:@" " startingAtIndex:0]; | |
NSString *changeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, change, order.changeDue]; | |
printString = [printString stringByAppendingString:changeLine]; | |
changeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, change, order.changeDue]; | |
printString = [printString stringByAppendingString:changeLine]; | |
changeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, change, order.changeDue]; | |
printString = [printString stringByAppendingString:changeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Transfer/Refund Policy and Footer | |
NSString *transferPolicy = @"All sales are final. Non-transferable."; | |
leftSpacing = ceil((45 - [transferPolicy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
transferPolicy = [padding stringByAppendingString:transferPolicy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, transferPolicy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
NSString *refundPolicy = @"No refunds. No exchanges."; | |
leftSpacing = ceil((45 - [refundPolicy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
refundPolicy = [padding stringByAppendingString:refundPolicy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, refundPolicy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
NSString *thankYouMessage = @"THANK YOU!"; | |
leftSpacing = ceil((45 - [thankYouMessage length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
thankYouMessage = [padding stringByAppendingString:thankYouMessage]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, thankYouMessage]; | |
// End of print | |
printString = [printString stringByAppendingString:@"^XZ"]; | |
// Feed the paper for tearing | |
length += 100; | |
printString = [NSString stringWithFormat:printString, length]; | |
NSLog(@"[PRINT STRING]: %@", printString); | |
NSData *commands = [printString dataUsingEncoding:NSASCIIStringEncoding]; | |
[weakSelf printReceiptAsOneJobUsingNSData:connection withData:[commands mutableCopy]]; | |
} | |
[connection close]; | |
}); | |
} | |
return YES; | |
} | |
- (BOOL)printRefundReceipt:(Order *)order { | |
NSLog(@"Printing refund receipt..."); | |
NSError *error = nil; | |
if ([[self connectedPrinterType] isEqualToString:@"[ZEBRA]"]) { | |
__block BOOL status = NO; | |
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; | |
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"]; | |
// Dispatch this task to the default queue | |
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ { | |
// Instantiate connection to Zebra Bluetooth accessory | |
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber]; | |
// Open the connection - physical connection is established here. | |
[connection open]; | |
status = [connection isConnected]; | |
if (status) { | |
NSError *error = nil; | |
[SGD SET:@"device.languages" withValue:@"zpl" andWithPrinterConnection:connection error:&error]; | |
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error]; | |
// Store the logo image on the printer | |
UIImage *logoImage = [UIImage imageNamed:@"logo-v5.png"]; | |
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil]; | |
[graphicsUtil storeImage:@"LOGO_V5" withImage:[logoImage CGImage] withWidth:logoImage.size.width andWithHeight:logoImage.size.height error:&error]; | |
// Spacing and length | |
int leftSpacing; | |
__block long length = 0; | |
NSString *padding; | |
// Start of print | |
__block NSString *printString = @"^XA^POI^PW576^MNN^LL%d^LH0,0"; | |
// Start off with 10 dots of padding | |
length += 10; | |
NSString *imageName = @"LOGO_V5"; | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, imageName]; | |
length += 150; | |
// Receipt Header | |
NSString *header = @"RECEIPT ONLY"; | |
leftSpacing = ceil((18 - [header length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
header = [padding stringByAppendingString:header]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,24,24^FO30,%ld^FD%@^FS", printString, length, header]; | |
// This portion is approximately 60 dots | |
length += 60; | |
// Terminal and Date line | |
// Terminal Number | |
NSString *terminalNumber = [NSString stringWithFormat:@"TERMINAL %03d", [[order valueForKey:@"deviceID"] intValue]]; | |
// Order Date | |
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; | |
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; | |
[dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss a"]; | |
NSString *dateString = [dateFormatter stringFromDate:order.completedAt]; | |
NSString *terminalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@ %@^FS", length, terminalNumber, dateString]; | |
printString = [printString stringByAppendingString:terminalString]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Order Number line | |
NSString *orderNumberString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FDOrder Number: %@^FS", length, order.orderNumber]; | |
printString = [printString stringByAppendingString:orderNumberString]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Line Items | |
NSArray *lineItems = [NSKeyedUnarchiver unarchiveObjectWithData:order.lineItems]; | |
for (id lineItem in lineItems) { | |
NSDictionary *line = [lineItem objectForKey:@"line_item"]; | |
NSString *ticketLabel = [line objectForKey:@"ticket_label"]; | |
NSString *quantity = [[line objectForKey:@"quantity"] stringValue]; | |
NSString *price = [line objectForKey:@"price"]; | |
NSString *unadjustedLineTotal = [line objectForKey:@"unadjusted_line_total"]; | |
NSString *product = [NSString stringWithFormat:@"%@ (%@ @ %@)", ticketLabel, quantity, price]; | |
product = [product stringByPaddingToLength:(45 - [unadjustedLineTotal length]) withString:@" " startingAtIndex:0]; | |
// Order Line Items | |
NSString *lineItemString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, product, unadjustedLineTotal]; | |
printString = [printString stringByAppendingString:lineItemString]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Order Discounts | |
NSArray *adjustments = [NSKeyedUnarchiver unarchiveObjectWithData:order.adjustments]; | |
NSArray *discounts = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Discount"]; | |
}]]; | |
NSArray *comps = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Comp"]; | |
}]]; | |
NSArray *wholesalers = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Wholesaler"]; | |
}]]; | |
NSArray *concierges = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Concierge"]; | |
}]]; | |
if ([discounts count] > 0) { | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
NSString *discountTotal = [@"Discount Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0]; | |
// Discount Total | |
NSString *discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, discountTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:discountTotalString]; | |
discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, discountTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:discountTotalString]; // Creates a bold effect | |
discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, discountTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:discountTotalString]; // Creates a bold effect | |
// This portion is approximately 25 dots | |
length += 25; | |
for (id discount in discounts) { | |
id discountObject = [discount objectForKey:@"adjustment"]; | |
NSDictionary *discountLabel = [discountObject objectForKey:@"label"]; | |
NSString *discountQuantity = [discountObject objectForKey:@"quantity"]; | |
NSString *discountUnitAmount = [discountObject objectForKey:@"formatted_unit_amount"]; | |
NSString *discountAmount = [discountObject objectForKey:@"formatted_total_amount"]; | |
NSString *discountString = [NSString stringWithFormat:@" %@ (%@ @ %@)", discountLabel, discountQuantity, discountUnitAmount]; | |
discountString = [discountString stringByPaddingToLength:(45 - [discountAmount length]) withString:@" " startingAtIndex:0]; | |
NSString *discountLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, discountString, discountAmount]; | |
printString = [printString stringByAppendingString:discountLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
} else if ([comps count] > 0) { | |
NSString *compTotal = [@"Comp Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, compTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:compLine]; | |
compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, compTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:compLine]; | |
compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, compTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:compLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} else if ([wholesalers count] > 0) { | |
NSString *wholesaleTotal = [@"Wholesale Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *wholesaleLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, wholesaleTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:wholesaleLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} else if ([concierges count] > 0) { | |
NSString *conciergeTotal = [@"Concierge Deposit:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, conciergeTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:conciergeLine]; | |
conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, conciergeTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:conciergeLine]; | |
conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, conciergeTotal, order.adjustmentTotal]; | |
printString = [printString stringByAppendingString:conciergeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Total Line | |
NSString *total = [@"TOTAL" stringByPaddingToLength:(45 - [order.orderTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, total, order.orderTotal]; | |
printString = [printString stringByAppendingString:totalLine]; | |
totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, total, order.orderTotal]; | |
printString = [printString stringByAppendingString:totalLine]; | |
totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, total, order.orderTotal]; | |
printString = [printString stringByAppendingString:totalLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
NSString *refundTotal = [@"REFUND TOTAL:" stringByPaddingToLength:(45 - [order.refundTotal length]) withString:@" " startingAtIndex:0]; | |
NSString *refundTotalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, refundTotal, order.refundTotal]; | |
printString = [printString stringByAppendingString:refundTotalLine]; | |
refundTotalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, refundTotal, order.refundTotal]; | |
printString = [printString stringByAppendingString:refundTotalLine]; | |
refundTotalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, refundTotal, order.refundTotal]; | |
printString = [printString stringByAppendingString:refundTotalLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Refund Detail | |
NSArray *refunds = [NSKeyedUnarchiver unarchiveObjectWithData:order.refunds]; | |
[refunds enumerateObjectsUsingBlock:^(id transaction, NSUInteger idx, BOOL *stop) { | |
NSDictionary *refund = [transaction objectForKey:@"refund"]; | |
NSString *gatewayTransactionID = [refund objectForKey:@"gateway_transaction_id"]; | |
NSString *cardType = [refund objectForKey:@"card_type"]; | |
NSString *cardNumber = [refund objectForKey:@"last_digits"]; | |
NSString *refundAmount = [refund objectForKey:@"amount"]; | |
refundAmount = [@"-" stringByAppendingString:refundAmount]; | |
NSString *cardTypeString = [[cardType uppercaseString] stringByPaddingToLength:(45 - [refundAmount length]) withString:@" " startingAtIndex:0]; | |
NSString *cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, cardTypeString, refundAmount]; | |
printString = [printString stringByAppendingString:cardTypeLine]; | |
cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, cardTypeString, refundAmount]; | |
printString = [printString stringByAppendingString:cardTypeLine]; | |
cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, cardTypeString, refundAmount]; | |
printString = [printString stringByAppendingString:cardTypeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
if ([cardNumber length] > 0) { | |
NSString *cardNumberString = [@" Card Number (last 4):" stringByPaddingToLength:(45 - [cardNumber length]) withString:@" " startingAtIndex:0]; | |
NSString *cardNumberLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, cardNumberString, cardNumber]; | |
printString = [printString stringByAppendingString:cardNumberLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
NSString *responseCodeString = [@" Transaction ID:" stringByPaddingToLength:(45 - [gatewayTransactionID length]) withString:@" " startingAtIndex:0]; | |
NSString *responseCodeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, responseCodeString, gatewayTransactionID]; | |
printString = [printString stringByAppendingString:responseCodeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
}]; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Transfer/Refund Policy and Footer | |
NSString *transferPolicy = @"All sales are final. Non-transferable."; | |
leftSpacing = ceil((45 - [transferPolicy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
transferPolicy = [padding stringByAppendingString:transferPolicy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, transferPolicy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
NSString *refundPolicy = @"No refunds. No exchanges."; | |
leftSpacing = ceil((45 - [refundPolicy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
refundPolicy = [padding stringByAppendingString:refundPolicy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, refundPolicy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
NSString *thankYouMessage = @"THANK YOU!"; | |
leftSpacing = ceil((45 - [thankYouMessage length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
thankYouMessage = [padding stringByAppendingString:thankYouMessage]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, thankYouMessage]; | |
// End of print | |
printString = [printString stringByAppendingString:@"^XZ"]; | |
// Feed the paper for tearing | |
length += 100; | |
printString = [NSString stringWithFormat:printString, length]; | |
NSLog(@"[PRINT STRING]: %@", printString); | |
NSData *commands = [printString dataUsingEncoding:NSASCIIStringEncoding]; | |
[self printReceiptAsOneJobUsingNSData:connection withData:[commands mutableCopy]]; | |
} | |
[connection close]; | |
}); | |
} | |
return YES; | |
} | |
- (BOOL)printTickets:(Order *)order { | |
NSError *error = nil; | |
if ([[self connectedPrinterType] isEqualToString:@"[ZEBRA]"]) { | |
__block BOOL status = NO; | |
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; | |
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"]; | |
// Dispatch this task to the default queue | |
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ { | |
// Instantiate connection to Zebra Bluetooth accessory | |
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber]; | |
// Open the connection - physical connection is established here. | |
[connection open]; | |
status = [connection isConnected]; | |
if (status) { | |
NSError *error = nil; | |
[SGD SET:@"device.languages" withValue:@"zpl" andWithPrinterConnection:connection error:&error]; | |
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error]; | |
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil]; | |
UIImage *image; | |
// Store the logo image on the printer | |
image = [UIImage imageNamed:@"logo-v5.png"]; | |
[graphicsUtil storeImage:@"LOGO_V5" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error]; | |
// Store the HOHO image on the printer | |
image = [UIImage imageNamed:@"hop-on-hop-off-tour-logo-v4.png"]; | |
[graphicsUtil storeImage:@"HOHO_V4" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error]; | |
// Store the BSS image on the printer | |
image = [UIImage imageNamed:@"bss-train-logo-v2.png"]; | |
[graphicsUtil storeImage:@"BSS_V2" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error]; | |
// Store the Cemetery image on the printer | |
image = [UIImage imageNamed:@"cemetery-tour-logo-v3.png"]; | |
[graphicsUtil storeImage:@"CEMETERY_V3" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error]; | |
// Store the Garden Tour image on the printer | |
image = [UIImage imageNamed:@"garden-tour-logo-v2.png"]; | |
[graphicsUtil storeImage:@"GARDEN_V2" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error]; | |
// Store the FQ Tour image on the printer | |
image = [UIImage imageNamed:@"french-quarter-tour-logo-v2.png"]; | |
[graphicsUtil storeImage:@"FQ_TOUR_V2" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error]; | |
// Spacing and length | |
NSString *padding; | |
int leftSpacing; | |
__block long length = 0; | |
// Start of print | |
__block NSString *printString = @"^XA^POI^PW576^MNN^LL%d^LH0,0"; | |
// Start off with 10 dots of padding | |
length += 10; | |
NSArray *lineItems = [NSKeyedUnarchiver unarchiveObjectWithData:order.lineItems]; | |
NSArray *adjustments = [NSKeyedUnarchiver unarchiveObjectWithData:order.adjustments]; | |
NSMutableArray *discounts = [[adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Discount"]; | |
}]] mutableCopy]; | |
NSMutableArray *comps = [[adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Comp"]; | |
}]] mutableCopy]; | |
NSMutableArray *wholesalers = [[adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Wholesaler"]; | |
}]] mutableCopy]; | |
NSMutableArray *concierges = [[adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { | |
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Concierge"]; | |
}]] mutableCopy]; | |
NSUInteger lineItemIndex = 0; | |
for (id lineItem in lineItems) { | |
NSDictionary *line = [lineItem objectForKey:@"line_item"]; | |
NSString *ticketLabel = [line objectForKey:@"ticket_label"]; | |
NSString *quantity = [[line objectForKey:@"quantity"] stringValue]; | |
for (int i = 0; i < [quantity integerValue]; i++) { | |
// Ticket Header | |
if ([ticketLabel containsString:@"FQ Tour"]) { | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"LOGO_V5"]; | |
length += 150; | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"FQ_TOUR_V2"]; | |
length += 150; | |
} else if ([ticketLabel containsString:@"Garden Tour"]) { | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"LOGO_V5"]; | |
length += 150; | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"GARDEN_V2"]; | |
length += 150; | |
} else if ([ticketLabel containsString:@"Cemetery Tour"]) { | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"BSS_V2"]; | |
length += 150; | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"CEMETERY_V3"]; | |
length += 150; | |
} else { | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"LOGO_V5"]; | |
length += 150; | |
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"HOHO_V4"]; | |
length += 150; | |
} | |
NSString *validRangeString = [line objectForKey:@"formatted_valid_range"]; | |
NSArray *rangeStringArray = [validRangeString componentsSeparatedByString: @"\n"]; | |
for (NSString *rangeString in rangeStringArray) { | |
leftSpacing = ceil((24 - [rangeString length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
NSString *rangeLine = [padding stringByAppendingString:rangeString]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,22^FO20,%ld^FD%@^FS", printString, length, rangeLine]; | |
// This portion is approximately 40 dots | |
length += 40; | |
} | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
NSString *cleanLabel = [ticketLabel stringByReplacingOccurrencesOfString:@"Audubon " withString:@""]; | |
cleanLabel = [NSString stringWithFormat:@"1 %@", cleanLabel]; | |
leftSpacing = ceil((23 - [cleanLabel length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
cleanLabel = [padding stringByAppendingString:cleanLabel]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,22^FO20,%ld^FD%@^FS", printString, length, cleanLabel]; | |
// This portion is approximately 40 dots | |
length += 40; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Barcode (PDF 417) | |
printString = [NSString stringWithFormat:@"%@^FO100,%ld^B7N,8,5,7,14,N^FD%@^FS", printString, length, order.orderNumber]; | |
// Barcode is approximately 140 dots | |
length += 140; | |
if ([discounts count] > 0) { | |
NSMutableDictionary *adjustment = [[discounts lastObject] mutableCopy]; | |
NSUInteger adjustmentIndex = [discounts indexOfObject:adjustment]; | |
NSMutableDictionary *discount = [[adjustment objectForKey:@"adjustment"] mutableCopy]; | |
NSString *discountLabel = [discount objectForKey:@"label"]; | |
NSNumber *discountQuantity = [discount objectForKey:@"quantity"]; | |
NSString *discountString = [NSString stringWithFormat:@"%@ %@", discountLabel, @"Discount"]; | |
if ([discountQuantity intValue] > 1) { | |
// Update the Discount Quantity | |
discountQuantity = [NSNumber numberWithInt:([discountQuantity intValue] - 1)]; | |
[discount setValue:discountQuantity forKey:@"quantity"]; | |
// Replace the Discount object in "discounts" array | |
[discounts replaceObjectAtIndex:adjustmentIndex withObject:@{@"adjustment":discount}]; | |
} else { | |
[discounts removeLastObject]; | |
} | |
NSString *saleTypeString = [@"Sale Type:" stringByPaddingToLength:(45 - [discountString length]) withString:@" " startingAtIndex:0]; | |
NSString *saleTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, saleTypeString, discountString]; | |
printString = [printString stringByAppendingString:saleTypeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
if ([comps count] > 0) { | |
NSString *saleTypeString = [@"Sale Type:" stringByPaddingToLength:(45 - [@"Complimentary" length]) withString:@" " startingAtIndex:0]; | |
NSString *saleTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, saleTypeString, @"Complimentary"]; | |
printString = [printString stringByAppendingString:saleTypeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} else if ([wholesalers count] > 0) { | |
NSString *saleTypeString = [@"Sale Type:" stringByPaddingToLength:(45 - [@"Wholesale" length]) withString:@" " startingAtIndex:0]; | |
NSString *saleTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, saleTypeString, @"Wholesale"]; | |
printString = [printString stringByAppendingString:saleTypeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} else if ([concierges count] > 0) { | |
NSString *saleTypeString = [@"Sale Type:" stringByPaddingToLength:(45 - [@"Concierge" length]) withString:@" " startingAtIndex:0]; | |
NSString *saleTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, saleTypeString, @"Concierge"]; | |
printString = [printString stringByAppendingString:saleTypeLine]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
// Ticket Purchase Details | |
// Terminal and Date line | |
// Terminal Number | |
NSString *terminalNumber = [NSString stringWithFormat:@"TERMINAL %03d", [[order valueForKey:@"deviceID"] intValue]]; | |
// Order Date | |
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; | |
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; | |
[dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss a"]; | |
NSString *dateString = [dateFormatter stringFromDate:order.completedAt]; | |
NSString *terminalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@ %@^FS", length, terminalNumber, dateString]; | |
printString = [printString stringByAppendingString:terminalString]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Order Number line | |
NSString *orderNumberString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FDOrder Number: %@^FS", length, order.orderNumber]; | |
printString = [printString stringByAppendingString:orderNumberString]; | |
// This portion is approximately 25 dots | |
length += 25; | |
// Add 25 dots of padding (about 1 line) | |
length += 25; | |
// Print Ticket Footer | |
if ([ticketLabel containsString:@"Cemetery Tour"]) { | |
NSString *policy = @"Tour Times: 9:30 10:30 11:30 12:30 1:30"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
NSString *padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"Present Ticket to Guide at Basin St. Station"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"First Come-First Serve; Limited to 28 guests."; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"Uneven Surfaces Everywhere - Watch your Step!"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} else if ([ticketLabel containsString:@"Tour"]) { | |
NSString *policy = @"Uneven Surfaces Everywhere - Watch your Step!"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
NSString *padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"Please give this ticket to Tour Host at"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"start of tour."; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"Space is Limited: 28 Guests per tour,"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"First come First serve."; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} else { | |
NSString *padding; | |
NSString *policy = @"Present Ticket to Bus Operator."; | |
int leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO19,%ld^FD%@^FS", printString, length, policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length+1, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"All Passengers must remain seated when"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"vehicle is in motion. No standing room."; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"Smoking, Eating, Drinking Alcoholic Beverages"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"is prohibited on vehicles."; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
policy = @"Route, Stops and Timing are subject to change"; | |
leftSpacing = ceil((45 - [policy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
policy = [padding stringByAppendingString:policy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
NSString *finalSalePolicy = @"All sales are final. Non-transferable."; | |
leftSpacing = ceil((45 - [finalSalePolicy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
finalSalePolicy = [padding stringByAppendingString:finalSalePolicy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, finalSalePolicy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
NSString *refundPolicy = @"No refunds. No exchanges."; | |
leftSpacing = ceil((45 - [refundPolicy length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
refundPolicy = [padding stringByAppendingString:refundPolicy]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, refundPolicy]; | |
// This portion is approximately 25 dots | |
length += 25; | |
} | |
NSString *thankYouMessage = @"THANK YOU!"; | |
leftSpacing = ceil((45 - [thankYouMessage length]) / 2); | |
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
thankYouMessage = [padding stringByAppendingString:thankYouMessage]; | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, thankYouMessage]; | |
// Feed the paper for tearing | |
length += 100; | |
// Print cut lines | |
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, @" ----------------------------------------------"]; | |
// Feed the paper for tearing | |
length += 100; | |
} | |
lineItemIndex++; | |
} | |
// End of print | |
printString = [printString stringByAppendingString:@"^XZ"]; | |
printString = [NSString stringWithFormat:printString, length]; | |
NSLog(@"[PRINT STRING]: %@", printString); | |
NSData *commands = [printString dataUsingEncoding:NSASCIIStringEncoding]; | |
[self printReceiptAsOneJobUsingNSData:connection withData:[commands mutableCopy]]; | |
} | |
[connection close]; | |
[self printReceipt:order]; | |
}); | |
// Increment Print Counter | |
[self incrementPrintCounter:order]; | |
} | |
return YES; | |
} | |
#pragma mark - Zebra Printer | |
- (BOOL)zebraPrinterStatus { | |
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; | |
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"]; | |
__block BOOL status = NO; | |
if ([serialNumber length] == 0) { | |
NSArray *accessories = [[EAAccessoryManager sharedAccessoryManager] connectedAccessories]; | |
NSString *zebraProtocol = @"com.zebra.rawport"; | |
for (EAAccessory *accessory in accessories) { | |
if ([[accessory protocolStrings] containsObject:zebraProtocol]) { | |
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; | |
NSLog(@"Setting zebraSerialNumber to %@", accessory.serialNumber); | |
serialNumber = accessory.serialNumber; | |
[preferences setObject:accessory.serialNumber forKey:@"zebraSerialNumber"]; | |
[preferences synchronize]; | |
break; | |
} | |
} | |
} | |
// Instantiate connection to Zebra Bluetooth accessory | |
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber]; | |
// Open the connection - physical connection is established here. | |
[connection open]; | |
status = [connection isConnected]; | |
[connection close]; | |
return status; | |
} | |
- (void)disableSleepMode { | |
__block BOOL status = NO; | |
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; | |
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"]; | |
if ([self zebraPrinterStatus]) { | |
//Dispatch this task to the default queue | |
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ { | |
// Instantiate connection to Zebra Bluetooth accessory | |
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber]; | |
// Open the connection - physical connection is established here. | |
[connection open]; | |
status = [connection isConnected]; | |
if (status) { | |
NSError *error = nil; | |
[SGD SET:@"power.sleep.enable" withValue:@"off" andWithPrinterConnection:connection error:&error]; | |
} | |
[connection close]; | |
}); | |
} | |
} | |
- (void)printZebraSelfTest { | |
__block BOOL status = NO; | |
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; | |
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"]; | |
// [self disableSleepMode]; | |
// Dispatch this task to the default queue | |
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ { | |
// Instantiate connection to Zebra Bluetooth accessory | |
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber]; | |
// Open the connection - physical connection is established here. | |
[connection open]; | |
status = [connection isConnected]; | |
if (status) { | |
NSError *error = nil; | |
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error]; | |
// [[printer getToolsUtil] reset:&error]; | |
[SGD SET:@"device.languages" withValue:@"zpl" andWithPrinterConnection:connection error:&error]; | |
// [SGD SET:@"power.sleep.enable" withValue:@"off" andWithPrinterConnection:connection error:&error]; | |
// [SGD SET:@"device.languages" withValue:@"line_print" andWithPrinterConnection:connection error:&error]; | |
NSString *sampleZplReceipt = [self createZplReceipt]; | |
NSData *sampleZplReceiptAsNsData = [sampleZplReceipt dataUsingEncoding:NSASCIIStringEncoding]; | |
// Store the logo image on the printer | |
UIImage *logoImage = [UIImage imageNamed:@"logo-v5.png"]; | |
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil]; | |
[graphicsUtil storeImage:@"LOGO_V5" withImage:[logoImage CGImage] withWidth:logoImage.size.width andWithHeight:logoImage.size.height error:&error]; | |
[self printReceiptAsOneJobUsingNSData:connection withData:[sampleZplReceiptAsNsData mutableCopy]]; | |
} | |
[connection close]; | |
}); | |
} | |
- (void)printReceiptAsOneJobUsingNSData:(id<NSObject,ZebraPrinterConnection>)connection withData:(NSMutableData*)commands { | |
/* | |
Sending large amounts of data in a single write command can overflow the NSStream buffers which are the underlying mechanism used by the SDK to communicate with the printers. | |
This method breaks up large data into smaller chunks to send to the printer | |
*/ | |
NSError *error = nil; | |
[connection open]; | |
[connection write:commands error:&error]; | |
NSLog(@"ERROR: %@", error); | |
// long blockSize = 1024; | |
// long totalSize = commands.length; | |
// long bytesRemaining = totalSize; | |
// | |
// while (bytesRemaining > 0) { | |
// long bytesToSend = MIN(blockSize, bytesRemaining); | |
// NSRange range = NSMakeRange(0, bytesToSend); | |
// | |
// NSData *partialChunk = [commands subdataWithRange:range]; | |
// [connection write:partialChunk error:&error]; | |
// NSLog(@"ERROR: %@", error); | |
// bytesRemaining -= bytesToSend; | |
// | |
// [commands replaceBytesInRange:range withBytes:NULL length:0]; | |
// } | |
} | |
- (NSString*)createZplReceipt { | |
NSString *printData = | |
@"^XA^POI^PW576^MNN^LL%ld^LH0,0" \ | |
@"^FO50,0^XGE:LOGO_V5.GRF,1,1^FS" \ | |
@"^A1,N,24,24" \ | |
@"^FO30,140^FDTEST RECEIPT ONLY^FS" \ | |
// Terminal and Date | |
@"%@" \ | |
// Order Number | |
@"%@" \ | |
@"^FO0,250" \ | |
@"^A2,N,12,12" \ | |
@"^FD ----------------------------------------------^FS" \ | |
// Barcode (PDF 417) | |
@"^FO100,280" \ | |
@"^B7N,8,5,7,14,N^FDCSS-000-YYMMDDHHMMSSSSS^FS" \ | |
@"^FO20,410" \ | |
@"^A2,N,12,12" \ | |
@"^FD%@^FS" \ | |
@"^XZ"; | |
long length = 500; | |
NSString *footer = @"No Refunds or Exchanges!"; | |
int leftSpacing = ceil((45 - [footer length]) / 2); | |
NSString *padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0]; | |
footer = [padding stringByAppendingString:footer]; | |
// Terminal and Date line | |
// Order Date | |
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; | |
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; | |
[dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss a"]; | |
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]]; | |
NSString *terminalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,200^FD%@ %@^FS", @"TERMINAL 001", dateString]; | |
// Order Number line | |
NSString *orderString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,225^FDOrder Number: %@^FS", @"CSS-000-YYMMDDHHMMSSSSS"]; | |
// Combine it all | |
NSString *printString = [NSString stringWithFormat:printData, length, terminalString, orderString, footer]; | |
return printString; | |
} | |
#pragma mark - Accessories | |
- (void)accessoryDidConnect:(NSNotification *)notification { | |
EAAccessory *accessory = [[notification userInfo] objectForKey:EAAccessoryKey]; | |
NSLog(@"[VP]: Accessory %@ has connected", accessory.serialNumber); | |
NSString *zebraProtocol = @"com.zebra.rawport"; | |
if ([accessory.protocolStrings containsObject:zebraProtocol]) { | |
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; | |
NSLog(@"Setting zebraSerialNumber to %@", accessory.serialNumber); | |
[preferences setObject:accessory.serialNumber forKey:@"zebraSerialNumber"]; | |
[preferences synchronize]; | |
} | |
} | |
- (void)accessoryDidDisconnect:(NSNotification *)notification { | |
EAAccessory *accessory = [[notification userInfo] objectForKey:EAAccessoryKey]; | |
NSLog(@"[VP]: Accessory %@ has disconnected", accessory.serialNumber); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment