package NightsBridge; use JSON; use Digest::MD5 qw(md5 md5_hex); use MIME::Base64 qw(encode_base64 decode_base64); use URI::Escape; use HTTP::Request; use HTTP::Request::Common; use LWP::UserAgent; use Data::Dumper; use DBI; use Time::localtime qw(localtime); =pre Base ON : Point of Sale API v1.1.pdf AccountID 6 Roomid 4 =cut sub postExtras{ my $opts = shift; my $dbh = $opts->{dbh}; my $invoice = $opts->{invoice}; my $client_id = $opts->{client}; my $invoice_account = $opts->{invoice_account}, #for default testing my $Base_Url = "https://www.nightsbridge.co.za/bridge/api/point-of-sale/1.0/establishments"; my $nightsbridge_username = $opts->{nightsbridge_username}; my $nightsbridge_password = $opts->{nightsbridge_password}; my $nightsbridge_bbid = $opts->{nightsbridge_bbid}; my $nightsbridge_bbid_pass= $opts->{nightsbridge_bbid_pass}; my $nightsbridge_accountId;#= $opts->{nightsbridge_accountId} || 6; my $nightsbridge_roomId = $opts->{nightsbridge_roomId}; my $fullName; my $room; print "Credientials are required\n" and return unless $nightsbridge_username && $nightsbridge_password && $nightsbridge_bbid && $nightsbridge_bbid_pass; my $tm = localtime(time); my $startdate = sprintf("%04d-%02d-%02d",($tm->year + 1900),($tm->mon+1),$tm->mday); my $tm2 = localtime(time + 14*24 * 60 * 60); my $enddate = sprintf("%04d-%02d-%02d",($tm2->year + 1900),($tm2->mon+1),$tm2->mday); #get Client in house. #my $cc = $dbh->selectrow_arrayref("SELECT * FROM nightbridge_guests WHERE created + INTERVAL 1 HOUR > NOW()"); #if(!$cc->[0]){ #my $URL = "$Base_Url/$nightsbridge_bbid/guests-in-house/$startdate/$enddate"; #getHouse($URL,$dbh,$nightsbridge_username,$nightsbridge_password); #} my $client = $dbh->selectrow_arrayref("SELECT nightsaccountId,nightsroomId FROM tillclients WHERE id =? ",undef,$client_id ); my $_nightsbridge_accountId = $client->[0]; my $_nightsbridge_roomId = $client->[1]; if($_nightsbridge_accountId && $_nightsbridge_roomId){ #if($_nightsbridge_roomId){ #get Guests in House and see if there is one matching . my $req = HTTP::Request::Common::GET "$Base_Url/$nightsbridge_bbid/guests-in-house/$startdate/$enddate"; $req->header('Authorization', 'Basic ' .encode_base64("$nightsbridge_username:$nightsbridge_password")); my $ua = LWP::UserAgent->new; my $res = $ua->request($req); #print $res->decoded_content; #logg($res->decoded_content); my $ret = JSON::decode_json($res->decoded_content); ### #print $res->decoded_content,"\n"; return "ERROR:".$ret->{message} ." Clent:$client_id, RoomID:" . $_nightsbridge_roomId if $ret->{code}; #100 101 102 my $flag = 0; foreach my $guest(@{$ret->{houseGuests}}){ my $roomid = $guest->{roomId}; my $accountid = $guest->{accountId}; my @fname; foreach my $client(@{$guest->{clients}}){ push @fname, $client->{fullName}; } if($accountid == $_nightsbridge_accountId && $roomid == $_nightsbridge_roomId){ #if($roomid == $_nightsbridge_roomId){ $nightsbridge_accountId = $accountid;#$_nightsbridge_accountId; $nightsbridge_roomId = $roomid;#$_nightsbridge_roomId; $fullName = join(",",@fname); $room = $guest->{roomName}; print "Guest:$accountid,$roomid,Client:$_nightsbridge_accountId,$_nightsbridge_roomId :"; print "matched\n"; $flag = 1; last; } } return "ERROR:No account and room id matched. Clent:$client_id,AccountID:$_nightsbridge_accountId,RoomID:$_nightsbridge_roomId \n" if $flag==0;# $nightsbridge_accountId && $nightsbridge_roomId; } my $query = "SELECT t.*,m.orgprice,m.code FROM tillordersdetails t LEFT JOIN menu m on m.id = t.plu WHERE t.invoice =?"; my $res = $dbh->selectall_arrayref($query , { Slice=>{} }, $invoice ); return if $#$res==-1 ;# no results. my $list = ARef($res); my $data; my $count = 0; my $total_amount = 0; my $plu; my $total =0; MENU:foreach(@$list){ next MENU if $_->{orgprice} == 0; $data->{posItems}->[$count]->{stockCode} = $_->{code}; $data->{posItems}->[$count]->{reference} = $_->{name}; $data->{posItems}->[$count]->{quantity} = formatNumber($_->{qty}) + 0; $data->{posItems}->[$count]->{price} = $_->{orgprice} + 0; $total_amount += $_->{orgprice} + 0; $total += $data->{posItems}->[$count]->{quantity} * $data->{posItems}->[$count]->{price}; $count++; $plu .= $data->{posItems}->[$count]->{stockCode} .","; $plu .= $data->{posItems}->[$count]->{reference} .","; $plu .= $data->{posItems}->[$count]->{quantity}.","; $plu .= $data->{posItems}->[$count]->{price}."\n"; } sub formatTip{ my $tip = shift; $tip = int($tip * 100)/100; if($tip !~/\./){ $tip = $tip . '.0'; } return $tip; } ##TIP invoice_account - $total = tip if($invoice_account - $total > 0){ my $tip = $invoice_account - $total; #$count++; $data->{posItems}->[$count]->{stockCode} = 'Tip001'; $data->{posItems}->[$count]->{reference} = 'Tip'; $data->{posItems}->[$count]->{quantity} = formatNumber("1.0")+ 0; $data->{posItems}->[$count]->{price} = formatTip($tip); print "Account:$invoice_account,Tip:$tip,Total:$total\n"; } $data->{accountId} = $nightsbridge_accountId;#$opts->{accountId} + 0; $data->{roomId} = $nightsbridge_roomId; #$opts->{roomId} + 0; $data->{tranDate} = $startdate; print Dumper($data); #https://www.nightsbridge.co.za/bridge/api/point-of-sale/1.0/establishments/34014/accounts/3/extras my $url = "$Base_Url/$nightsbridge_bbid/accounts/$nightsbridge_accountId/extras"; my $req = HTTP::Request::Common::POST $url, Content_Type => 'application/json', Content => JSON::encode_json($data); $req->header('Authorization', 'Basic ' .encode_base64("$nightsbridge_username:$nightsbridge_password")); my $ua = LWP::UserAgent->new; print "AccountId:" . $nightsbridge_accountId . " RoomID:" . $nightsbridge_roomId. " guests:" .$fullName."\n"; eval{ my $res = $ua->request($req); #print $res->status_line; print "$fullName , $room \n".$res->decoded_content,"\n"; my $ret = JSON::decode_json($res->decoded_content); if($ret->{code}){ print $ret->{code} ." , " . $ret->{message}."\n"; }else{ my $log_content = "$fullName , $room\n AccountID:".$ret->{accountId} .",Count:" . $ret->{count} .",RoomID:" .$data->{roomId} ."\n" .$plu; logg($log_content,$startdate); } }; #&postPayments($nightsbridge_username,$nightsbridge_password,$nightsbridge_bbid,$nightsbridge_bbid_pass,$nightsbridge_accountId,$nightsbridge_roomId,$total_amount,$invoice); return "OK"; } sub postPayments { my($nightsbridge_username,$nightsbridge_password,$nightsbridge_bbid,$nightsbridge_bbid_pass,$nightsbridge_accountId,$nightsbridge_roomId,$total_amount,$invoice) = @_; print "$total_amount,$invoice\n"; #for default testing my $Base_Url = "https://www.nightsbridge.co.za/bridge/api/point-of-sale/1.0/establishments"; my $tm = localtime(time); my $startdate = sprintf("%04d-%02d-%02d",($tm->year + 1900),($tm->mon+1),$tm->mday); my $data; $data->{tranDate} = $startdate; $data->{accountId} = $nightsbridge_accountId; $data->{tranType} = 'OTHER'; $data->{reference} = 'INV '.$invoice; $data->{amount} = $total_amount; my $url = "$Base_Url/$nightsbridge_bbid/accounts/$nightsbridge_accountId/payments"; my $req = HTTP::Request::Common::POST $url, Content_Type => 'application/json', Content => JSON::encode_json($data); $req->header('Authorization', 'Basic ' .encode_base64("$nightsbridge_username:$nightsbridge_password")); my $ua = LWP::UserAgent->new; eval{ my $res = $ua->request($req); #print $res->status_line; print $res->decoded_content,"\n"; logg($res->decoded_content); }; } sub getHouse{ #my($URL,$dbh,$nightsbridge_username,$nightsbridge_password) = @_; my $opts = shift; my $dbh = $opts->{dbh}; #for default testing my $Base_Url = "https://www.nightsbridge.co.za/bridge/api/point-of-sale/1.0/establishments"; my $nightsbridge_username = $opts->{nightsbridge_username}; my $nightsbridge_password = $opts->{nightsbridge_password}; my $nightsbridge_bbid = $opts->{nightsbridge_bbid}; my $nightsbridge_bbid_pass= $opts->{nightsbridge_bbid_pass}; my $nightsbridge_accountId;#= $opts->{nightsbridge_accountId} || 6; my $nightsbridge_roomId;# = $opts->{nightsbridge_roomId} || 4; my $tm = localtime(time); my $startdate = sprintf("%04d-%02d-%02d",($tm->year + 1900),($tm->mon+1),$tm->mday); my $tm2 = localtime(time + 1*24 * 60 * 60); my $enddate = sprintf("%04d-%02d-%02d",($tm2->year + 1900),($tm2->mon+1),$tm2->mday); my $req = HTTP::Request::Common::GET "$Base_Url/$nightsbridge_bbid/guests-in-house/$startdate/$enddate"; $req->header('Authorization', 'Basic ' .encode_base64("$nightsbridge_username:$nightsbridge_password")); my $ua = LWP::UserAgent->new; my $res = $ua->request($req); #print $res->status_line; print $res->decoded_content; my $ret = JSON::decode_json($res->decoded_content); local *get_password = sub { my @range = ('0'..'9'); my $x = int scalar @range; return join '', map $range[rand $x], 1..4||1; }; if($ret->{code}){ #print Dumper($ret);die(0); 100 101 102, bypasssss. }else{ $dbh->do("UPDATE nightbridge_guests SET clients=?,created=NOW()",undef,$res->decoded_content); #search tillclients. #START .... foreach my $guest(@{$ret->{houseGuests}}){ my $roomid = $guest->{roomId}; my $accountid = $guest->{accountId}; my @fname; foreach my $client(@{$guest->{clients}}){ #push @fname, $client->{fullName}; my $firstname = $client->{firstName}; my $surename = $client->{surname}; my $clientid = $client->{clientId}; my $fullname = $client->{fullName}; my $tillclient = $dbh->selectrow_hashref("SELECT * FROM tillclients WHERE nights_clientid =? LIMIT 1 ",undef,$clientid ); unless( $tillclient->{id}){ $tillclient = $dbh->selectrow_hashref("SELECT * FROM tillclients WHERE firstname =? AND lastname=? LIMIT 1 ",undef, $firstname,$surename); } if( $tillclient->{id}){#update its account and roomid $dbh->do("UPDATE tillclients SET nightsaccountId=?,nightsroomId=? WHERE id=?",undef, $accountid, $roomid,$tillclient->{id}); }else{#add $dbh->do("INSERT INTO tillclients SET shop_id=?, password=?, code=?, firstname=?, lastname=?, nightsaccountId=?, nightsroomId=?, nights_clientid=?, active=1, createddate=NOW(), f_status=1, created=NOW(), clientgroup='NightsBridge', name=?, nights_fullname=?, nights_firstname=?, nights_surename=? ",undef, 1, get_password(), get_password(), $firstname, $surename, $accountid, $roomid, $clientid, $fullname, $fullname||'', $firstname||'', $surename||'' ); } } } =pre if($accountid == $_nightsbridge_accountId && $roomid == $_nightsbridge_roomId){ #if($roomid == $_nightsbridge_roomId){ $nightsbridge_accountId = $accountid;#$_nightsbridge_accountId; $nightsbridge_roomId = $roomid;#$_nightsbridge_roomId; $fullName = join(",",@fname); $room = $guest->{roomName}; print "Guest:$accountid,$roomid,Client:$_nightsbridge_accountId,$_nightsbridge_roomId :"; print "matched\n"; $flag = 1; last; } =cut } } sub formatNumber{ my $number = shift; my ($shorten) = $number=~m|(\d+\.\d)|; return $shorten; } sub ARef { my $data = shift; return [] unless $data; return [$data] unless ref($data) eq 'ARRAY'; return $data; } sub logg{ my ($content,$date) = @_; my $dir = "/wwwroot/extranet/pos/nightbridge_log"; unless(-e "$dir/$date" ."_log.txt" ){ open FILE, ">$dir/$date" ."_log.txt"; close FILE; } open LOG,">>$dir/$date" ."_log.txt" ; print LOG $content."\n--------------------------\n"; close LOG; } =pre sub getHouse{ my($startdate,$enddate) = @_; my $req = HTTP::Request::Common::GET "$nightsbridge_baseURL/guests-in-house/$startdate/$enddate"; $req->header('Authorization', 'Basic ' .encode_base64("$nightsbridge_username:$nightsbridge_password")); my $ua = LWP::UserAgent->new; my $res = $ua->request($req); #print $res->status_line; #print $res->decoded_content; my $ret = JSON::decode_json($res->decoded_content); if($ret->{code}){ #print Dumper($ret);die(0); 100 101 102 } print Dumper($ret); return $ret; {"tranDate":"2022-11-24", "posItems":[ {"stockCode":"781718446181","quantity":"1.0","reference":"BON APETIT 500 G","price":"19.90"}, {"stockCode":"6009611360590","quantity":"1.0","price":"35.90","reference":"BOWMANS CRUSHED GARLIC 500G"} ], "roomId":3,"accountId":"4"} ==================== { "accountId": 5, "roomId": 1, "tranDate": "2022-11-24", "posItems": [ { "stockCode": "6009611360590", "quantity": 1.5, "price": 19.90, "reference" : "BOWMANS CRUSHED GARLIC 500G"}, { "stockCode": "6009611360591", "quantity": 1.0, "price": 19.90, "reference" : "BOWMANS CRUSHED GARLIC 500G 2"} ] } ==================== 'houseGuests' => [ { 'roomId' => 3, 'clients' => [ { 'surname' => 'Stanford', 'clientId' => 86015919, 'fullName' => 'Niel Stanford', 'firstName' => 'Niel' } ], 'arrival' => '2022-11-27', 'roomName' => 'CHALET 1', 'bookingId' => 80086258, 'accountId' => 4, 'departure' => '2022-12-08' }, { 'accountId' => 4, 'departure' => '2022-12-19', 'arrival' => '2022-12-06', 'bookingId' => 80086267, 'roomName' => 'ROOM 1', 'roomId' => 1, 'clients' => [ { 'firstName' => 'Niel', 'fullName' => 'Niel Stanford', 'clientId' => 86015919, 'surname' => 'Stanford' } ] }, { 'clients' => [ { 'surname' => 'Test', 'clientId' => 86241662, 'fullName' => 'Test Test', 'firstName' => 'Test' } ], 'roomId' => 1, 'departure' => '2022-12-01', 'accountId' => 5, 'bookingId' => 80316845, 'arrival' => '2022-11-23', 'roomName' => 'ROOM 1' } ] }; } ================ sub postPayments{ my($opts) = @_; # opts : $opts->{accountId} tranDate tranType reference amount # tranType : BANK CASH CREDIT_CARD OTHER my $data; $data->{accountId} = $opts->{houseGuests}->[0]->{accountId}; $data->{tranDate} = $opts->{tranDate}; $data->{tranType} = $opts->{tranType}; $data->{reference} = $opts->{reference}; $data->{amount} = $opts->{amount}; my $url = "$nightsbridge_baseURL/accounts/$data->{accountId}/payments"; my $req = HTTP::Request::Common::POST $url, Content_Type => 'application/json', Content => JSON::encode_json($data); $req->header('Authorization', 'Basic ' .encode_base64("$nightsbridge_username:$nightsbridge_password")); my $ua = LWP::UserAgent->new; my $res = $ua->request($req); my $ret = JSON::decode_json($res->decoded_content); print Dumper($ret); } =cut 1;