Simultaneous User Layout Printing and Order Saving
Task: To create a script that will simultaneously print a user layout at the cash station and save an order. The script uses a function key that runs a user selector.
Solution:
procedure ProcessOperation1001188(Parameter: integer); begin RK7.PerformRefObject( RK7.FindItemByCode(rkrefMaketSchemeDetails, 127) ); RK7.PostOperation(rkoSaveOrder, 0); end;
Full Receipt Deleting
Task: To create a script that will delete fully receipts.
Solution:
procedure ProcessOperation1000522(Parameter: integer); var it: TCheckItem; begin if GUI.CheckFormInPayMode then Exit; if RK7.CashUser.ConfirmOperation(rkoCreateVoid) = False then Exit; RK7.PerformOperation(rkoHome, 0); while True do begin it := RKCheck.CurrentCheckItem; if TObject(it) = Nil then break; if SYS.ObjectInheritsFrom(TObject(it), 'TPrintCheckItem') then break; if SYS.ObjectInheritsFrom(TObject(it), 'TDiscountItem') then begin if (TDiscountItem(it).ChargeSource <> chsAuto) and (it.State = disOpened) then begin RK7.PerformOperation(rkoDeleteLine, 1); continue; end; end else if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then begin if it.State = disOpened then begin RK7.PerformOperation(rkoDeleteLine, 1); continue; end else RKCheck.CreateCheckItem(rkrefOrderVoids, '1', FloatToStr(TDish(it).Quantity)); end; RK7.PerformOperation(rkoDown, 0); end; RK7.PerformOperation(rkoCloseMode, 0); RK7.PerformOperation(rkoPackDishes, 0); end;
Creating the Function Key "Delete All Menu Elements from the Order" Including Tariffications But not Discounts
Task: To create a script for the button that will delete all the contents leaving only the order properties and discounts, extra charges, and prepayments. Only one delete reason should be specified for all the elements to be deleted.
Solution:
procedure ProcessOperation1000998(Parameter: integer); var it: TCheckItem; VoidCode, step: integer; ed: TObject; begin step := 0; if GUI.CheckFormInPayMode then Exit; if RK7.CashUser.ConfirmOperation(rkoCreateVoid) = False then Exit; VoidCode := -1; ed := TObject(gui.FindComponentByName('Editor')); if SYS.ObjectInheritsFrom(TObject(ed), 'TNumEditor') then begin if TNumEditor(ed).Text='' then begin gui.showmessage('Deletion reason code not indicated!'); Exit; end else VoidCode := StrToInt(TNumEditor(ed).Text); end; if VoidCode<0 then Exit; RK7.PerformOperation(rkoHome, 0); while step< RKCheck.CurrentOrder.Sessions.LinesCount do begin it := RKCheck.CurrentCheckItem; if TObject(it) = Nil then break; if SYS.ObjectInheritsFrom(TObject(it), 'TPrintCheckItem') then break; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then begin if it.State = disOpened then begin // dbg.dbgprint('delete dish'); RK7.PerformOperation(rkoDeleteLine, 1); // deletion continue; end else begin // dbg.dbgprint('void dish'); RKCheck.CreateCheckItem(rkrefOrderVoids, IntToStr(VoidCode), FloatToStr(TDish(it).Quantity)); // write-off end; end; // dbg.dbgprint('move down'); step := step + 1; RK7.PerformOperation(rkoDown, 0); end; end;
Creating Free Dish Special Offer for Workdays If an Order Exceeds 1000 Rubles
Task: On workdays, when an order reaches the amount of 1000 rubles and the Save Order button is pressed, an offer appears to add a free beer (brand No. 1).
If the order amount reaches 2000 rubles, the system suggests another beer (brand No. 2) or two beers of brand No. 1.
Solution: Create a script for the user operation that should be assigned for the selector instead of the standard order saving selector:
procedure ProcessOperation1002227(Parameter: integer); var i, DishCode1,DishCode2: integer; qnt1, qnt2, qntMax11, qntMax12, qntMax21, qntMax22: double; checksum, LimitSum1,LimitSum2: double; it: TCheckItem; CurrTime, Time1, Time2: TDateTime; begin if not RKCheck.Valid then exit; //important checking //********** Set parameters ***********// DishCode1 := 45; // controlled dish1 code DishCode2 := 46; // controlled dish2 code qntMax11 := 1; // the maximum quantity of controlled dish1 in an order exceeding 1000 rub. qntMax12 := 0; // the maximum quantity of controlled dish2 in an order exceeding 1000 rub. qntMax21 := 2; // the maximum quantity of controlled dish1 in an order exceeding 2000 rub. qntMax22 := 1; // the maximum quantity of controlled dish2 in an order exceeding 2000 rub. Time1 := EncodeTime(10,00,00,00); // special offer start Time2 := EncodeTime(18,00,00,00); // special offer end LimitSum1 := 1000; // a receipt amount that, if exceeded, allows to add a bonus dish. LimitSum2 := 2000; // a receipt amount that, if exceeded, allows to add a bonus dish. //********** Set parameters ***********// qnt1 := 0; qnt2 := 0; CurrTime := Time; checksum := 0; //1 = Sunday //2 = Monday //3 = Tuesday //4 = Wednesday //5 = Thursday //6 = Friday //7 = Saturday begin if (DayOfWeek(Now)>=2)and(DayOfWeek(Now)<=6) then // day of the week check if (Time1<=CurrTime)and(CurrTime<=Time2) then begin checksum := RKCheck.CurrentOrder.ToPaySum; for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; if SYS.ObjectInheritsFrom(it, 'TDish') then begin if TDish(it).code = DishCode1 then qnt1 := qnt1 + TDish(it).Quantity; if TDish(it).code = DishCode2 then qnt2 := qnt2 + TDish(it).Quantity; end; end; if (checksum >= LimitSum1) and (checksum < LimitSum2) then begin if (qnt1 < qntMax11) then // check limit exceed if GUI.RKMessageDlg('Do you want to add a free dish Beer1?', 0, 3, 100000) = 6 then begin RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(DishCode1), IntToStr(Trunc(qntMax11))); RK7.PerformOperation(rkoSaveOrder, 0); exit; end; end else if (checksum >= LimitSum2) then begin if (qnt2 < qntMax22) then // check limit exceed if GUI.RKMessageDlg('Do you want to add a free dish beer2?', 0, 3, 100000) = 6 then begin RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(DishCode2), IntToStr(Trunc(qntMax22))); RK7.PerformOperation(rkoSaveOrder, 0); exit; end else if (qnt1 < qntMax21) then // check limit exceed if GUI.RKMessageDlg('Do you want to add a free dish Beer1?', 0, 3, 100000) = 6 then begin RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(DishCode1), IntToStr(Trunc(qntMax21))); RK7.PerformOperation(rkoSaveOrder, 0); exit; end; end; end; end; RK7.PerformOperation(rkoSaveOrder, 0); end;
Creating 3 for 2 Special Offer
Task: to create the "3 for the price of 2" special offer
Solution: at the r_keeper 7 manager station, go to Money > Discounts and Markups, create a new discount with the following properties:
- Count type: Amount
- Changeable Value: enabled
- Allow Multiple: enabled
- On Dish: enabled.
Assign the following script to the selector:
procedure ProcessOperation1001326(Parameter: integer); var i, j, k: integer; it: TCheckItem; d: TDish; a, PaySum, q: double; str: string; info: string; DiscCode: integer; Categ: TClassificatorGroup; begin RK7.PerformOperation(rkoPackDishes, 0); DiscCode := 11; // discount code info := ';'; RK7.PerformOperation(rkoHome, 0); while True do begin it := RKCheck.CurrentCheckItem; if TObject(it) = Nil then break; Categ := TClassificatorGroup(RK7.FindItemByCode(rkrefClassificatorGroups, 8)); // indicate classification code if SYS.ObjectInheritsFrom(TObject(it), 'TEmptyLine') then break; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then if Categ.IsChild(it. RefItem) then begin // if a dish belongs to the specified classification, you can move on. d := TDish(it); PaySum := d.PaySum; for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) and SYS.ObjectInheritsFrom(TObject(it), 'TDiscountItem') then begin PaySum := PaySum - TDiscountItem(it).CalcAmount; RKCheck.DeleteCheckItem(it); end; end; i := Pos(';' + IntToStr(d.Sifr) + '=', info); if i = 0 then a := 0 else begin str := Copy(info, i+1, 10000); k := Pos(';', str); str := Copy(info, i+1, k - 1); Delete(info, i, k); a := StrToFloat(Copy(str, Pos('=', str)+1, 10000)); end; a := a + d.Quantity; if a > 2 then begin q := int64(Trunc(a) div 3); a := a - 3*q; str := FloatToStr(PaySum*q/d.Quantity); RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), str); end; info := info + IntToStr(d.Sifr) + '=' + FloatToStr(a) + ';'; end; RK7.PerformOperation(rkoDown, 0); end; end;
Creating a 50% Discount on Every Second Dish in the Order
Task: a script is required for creating a 50% discount on every second dish in the order.
Solution: create a new discount, then a new detail for it, with the following properties:
- Min. quantity: 2
- Qty mode: For all
- Percent: 50
Assign the following script to the selector:
procedure ProcessOperation1002352(Parameter: integer); var i, j, k: integer; it: TCheckItem; d: TDish; a, PaySum, q, perc: double; str: string; info: string; DiscCode: integer; begin RK7.PerformOperation(rkoPackDishes, 0); DiscCode := 11; // the code of the opened fixed amount discount on a dish perc := 0.5; // disount % info := ';'; RK7.PerformOperation(rkoHome, 0); while True do begin it := RKCheck.CurrentCheckItem; if TObject(it) = Nil then break; if SYS.ObjectInheritsFrom(TObject(it), 'TEmptyLine') then break; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then begin d := TDish(it); PaySum := d.PaySum; for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) and SYS.ObjectInheritsFrom(TObject(it), 'TDiscountItem') then begin PaySum := PaySum - TDiscountItem(it).CalcAmount; RKCheck.DeleteCheckItem(it); end; end; dbg.dbgprint('PaySum = '+floattostr(PaySum)); i := Pos(';' + IntToStr(d.Sifr) + '=', info); if i = 0 then a := 0 else begin str := Copy(info, i+1, 10000); k := Pos(';', str); str := Copy(info, i+1, k - 1); Delete(info, i, k); a := StrToFloat(Copy(str, Pos('=', str)+1, 10000)); end; dbg.dbgprint('str = '+(str)); a := a + d.Quantity; dbg.dbgprint('a = '+floattostr(a)); if a > 1 then begin q := int64(Trunc(a) div 2); a := a - 2*q; str := FloatToStr(PaySum*q/d.Quantity*perc); dbg.dbgprint('str = '+(str)); RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), str); end; info := info + IntToStr(d.Sifr) + '=' + FloatToStr(a) + ';'; end; RK7.PerformOperation(rkoDown, 0); end; end;
This script applies the 50% discount to all positions after the first one.
If you need a discount on every second dish, edit the following strings:
if a > 1 then begin q := int64(Trunc(a) div 2); a := a - 2*q;
Creating a100% Discount for the Second Dish of a Certain Category in the Order
Task: to create a 100% discount on the second dish of a certain category.
Solution:
procedure ProcessOperation1000695(Parameter: integer); var i, j, k: integer; it: TCheckItem; d: TDish; a, PaySum, q: double; str: string; info: string; DiscCode: integer; begin RK7.PerformOperation(rkoPackDishes, 0); DiscCode := 32; info := ';'; RK7.PerformOperation(rkoHome, 0); while True do begin it := RKCheck.CurrentCheckItem; if TObject(it) = Nil then break; if SYS.ObjectInheritsFrom(TObject(it), 'TEmptyLine') then break; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then begin d := TDish(it); PaySum := d.PaySum; for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) and SYS.ObjectInheritsFrom(TObject(it), 'TDiscountItem') then begin PaySum := PaySum - TDiscountItem(it).CalcAmount; RKCheck.DeleteCheckItem(it); end; end; i := Pos(';' + IntToStr(d.Sifr) + '=', info); if i = 0 then a := 0 else begin str := Copy(info, i+1, 10000); k := Pos(';', str); str := Copy(info, i+1, k - 1); Delete(info, i, k); a := StrToFloat(Copy(str, Pos('=', str)+1, 10000)); end; a := a + d.Quantity; if a > 1 then begin q := int64(Trunc(a) div 2); a := a - 2*q; str := FloatToStr(PaySum*q/d.Quantity); RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), str); end; info := info + IntToStr(d.Sifr) + '=' + FloatToStr(a) + ';'; end; RK7.PerformOperation(rkoDown, 0); end; end;
Creating a 100% Discount on the First Dish from the Category
Task: To create a special flyer offer — one free dessert for the receipt amount from 500 rubles. A 100% percent discount only on the dish from the dessert category. Prices are different, a receipt can contain several desserts. A discount should be applied only once, to the dessert that is the first in the order.
Solution:
The script for adding a special offer manually:
procedure ProcessOperation1001621(Parameter: integer); var i, j, numcateg: integer; DiscCode: integer; it, CurItem: TCheckItem; SL: TStringList; a, q, Price: double; d: TDish; CheckView: TCheckView; Categ: TClassificatorGroup; skip: boolean; begin CheckView := TCheckView(GUI.FindComponentByName('CheckView')); if CheckView = Nil then Exit; CurItem := RKCheck.CurrentCheckItem; SL := TStringList.Create; try // Create list of the dishes, sorted by price SL.Sorted := True; DiscCode := 11; numcateg := 8; //5 - category code for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; Categ := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', numcateg)); //5 - category code if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then //Check dish lines only if Categ.IsChild(it.RefItem) then //Check category of the dish // if (it.RefItem.MainParent.code =11 ) then // if dish from category of menu and have same code if ((it.State = disOpened) or (it.State = disPrinted)) then if TDish(it).Quantity > 0 then begin if SL.Count<1 then begin if (TDish(it).Quantity = 0) or (TDish(it).PRListSum = 0) then Price := TDish(it).Price else Price := TDish(it).PRListSum/TDish(it).Quantity; SL.AddObject(FormatFloat('00000000.00', Price) + IntToStr(TDish(it).UNI), TObject(it)); end; end; end; //Magic q:=0; for i:= 0 to SL.Count - 1 do begin a:= 0; d:= TDish(SL.Objects[i]); q:= d.Quantity; if (d.Quantity = 0) or (d.PRListSum = 0) then Price := d.Price else Price := d.PRListSum/d.Quantity; a:= a + Price; if RKCheck.CurrentOrder.UnpaidSum-a >= 500 then begin // Delete discount if the sum changed for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then begin if abs(TDiscountItem(it).CalcAmount) = a then a := 0 else begin RKCheck.DeleteCheckItem(it); end; break; end; end; // Create discount to a dish if a > 0 then begin CheckView.GotoItem(TObject(d)); RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), FloatToStr(a)); end; end else begin // Delete discount if the sum changed for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then begin // gui.showmessage('44444'); RKCheck.DeleteCheckItem(it); break; end; end; end; end; finally SL.Free(); if CurItem <> Nil then CheckView.GotoItem(CurItem); end; RKCheck.CurrentOrder.Recalc(); end;
Two scripts for the receipt editing form that automatically add or delete a discount:
procedure CheckViewOnAfterCheckViewEdit(Sender: TObject; AEditType: TEditType; AObjectBef, AObjectAft: TObject); var i, j, numcateg, OrderTypeCode, GuestTypeIdent: integer; DiscCode, HaveDisc: integer; it, CurItem: TCheckItem; SL: TStringList; newsum, aftersum, beforesum, limitsum, topay, a, q, Price: double; d: TDish; CheckView: TCheckView; Categ: TClassificatorGroup; begin CheckView := TCheckView(GUI.FindComponentByName('CheckView')); if CheckView = Nil then Exit; HaveDisc := 0; // ****************************************************************** DiscCode := 11; // discount code for the special dish numcateg := 8; // category code for the special dish limitsum := 500; // min order amount with all discounts OrderTypeCode := 1; // order type code GuestTypeIdent := 1000087; // guest type id // ****************************************************************** CurItem := RKCheck.CurrentCheckItem; SL := TStringList.Create; // if (RKCheck.CurrentOrder.OrderTypeCode = 2) then // for different OrderTypeCode // if (RKCheck.CurrentOrder.OrderCategoryCode = 2) then // for different OrderCategoryCode // if (RKCheck.CurrentOrder.Visit.GuestType = 0) then // for different GuestType if (RKCheck.CurrentOrder.OrderTypeCode = OrderTypeCode) // for different OrderTypeCode or(RKCheck.CurrentOrder.Visit.GuestType = GuestTypeIdent) // for different GuestType then try // Create list of the dishes, sorted by price SL.Sorted := False; for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; Categ := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', numcateg)); //5 - category code // if SYS.ObjectInheritsFrom(TObject(it), 'TDiscountItem') then // if TDiscountItem(it).code = 11 then // gui.showmessage('111111111'); // if TDiscountItem(it).CalcAmount > 0 then // HaveDisc := HaveDisc + 1; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then //Check dish lines only if Categ.IsChild(it.RefItem) then //Check category of the dish // if (it.RefItem.MainParent.code =11 ) then // if dish from categore of menu and have same code if ((it.State = disOpened) or (it.State = disPrinted)) then if TDish(it).Quantity > 0 then begin if SL.Count<1 then begin if (TDish(it).Quantity = 0) or (TDish(it).PRListSum = 0) then Price := TDish(it).Price else Price := TDish(it).PRListSum/TDish(it).Quantity; SL.AddObject(FormatFloat('00000000.00', Price) + IntToStr(TDish(it).UNI), TObject(it)); end; end; end; //Magic q:=0; newsum := 0; aftersum := 0; beforesum := 0; if SYS.ObjectInheritsFrom(AObjectAft, 'TDish') then aftersum := TDish(AObjectAft).PRListSum else aftersum := 0; if SYS.ObjectInheritsFrom(AObjectBef, 'TDish') then beforesum := TDish(AObjectBef).PRListSum else beforesum := 0; newsum := aftersum-beforesum; for i:= 0 to SL.Count - 1 do begin a:= 0; d:= TDish(SL.Objects[i]); q:= d.Quantity; if (d.Quantity = 0) or (d.PRListSum = 0) then Price := d.Price else Price := d.PRListSum/d.Quantity; a:= a + Price; // search special discount for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then HaveDisc := HaveDisc + 1; end; if HaveDisc > 0 then topay := RKCheck.CurrentOrder.UnpaidSum + a else topay := RKCheck.CurrentOrder.UnpaidSum; if topay-a+newsum >= limitsum then begin // Delete discount, if a sum changed for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then begin if abs(TDiscountItem(it).CalcAmount) = a then a := 0 else begin RKCheck.DeleteCheckItem(it); end; break; end; end; // Create discount to a dish if a > 0 then begin CheckView.GotoItem(TObject(d)); RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), FloatToStr(a)); end; end else begin // Delete discount, if a sum changed for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then begin RKCheck.DeleteCheckItem(it); break; end; end; end; end; finally SL.Free(); if CurItem <> Nil then CheckView.GotoItem(CurItem); end; RKCheck.CurrentOrder.Recalc(); end; procedure CheckViewOnBeforeCheckViewEdit(Sender: TObject; AEditType: TEditType; AObjectBef, AObjectAft: TObject; var AAllow: boolean; var AMessage: string); var i, j, numcateg, OrderTypeCode, GuestTypeIdent: integer; DiscCode, HaveDisc: integer; it, CurItem: TCheckItem; SL: TStringList; newsum, aftersum, beforesum, limitsum, topay, a, q, Price: double; d: TDish; CheckView: TCheckView; Categ: TClassificatorGroup; begin CheckView := TCheckView(GUI.FindComponentByName('CheckView')); if CheckView = Nil then Exit; HaveDisc := 0; // ****************************************************************** DiscCode := 11; // discount code for the special dish numcateg := 8; // category code for the special dish limitsum := 500; // min order amount with all the discounts OrderTypeCode := 1; // order type code GuestTypeIdent := 1000087; // guest type id // ****************************************************************** CurItem := RKCheck.CurrentCheckItem; SL := TStringList.Create; // if (RKCheck.CurrentOrder.OrderTypeCode = 2) then // for different OrderTypeCode // if (RKCheck.CurrentOrder.OrderCategoryCode = 2) then // for different OrderCategoryCode // if (RKCheck.CurrentOrder.Visit.GuestType = 0) then // for different GuestType if (RKCheck.CurrentOrder.OrderTypeCode = OrderTypeCode) // for different OrderTypeCode or(RKCheck.CurrentOrder.Visit.GuestType = GuestTypeIdent) // for different GuestType then if AEditType = etRemove then try // Create list of the dishes, sorted by price SL.Sorted := False; for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; Categ := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', numcateg)); //5 - category code if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then //Check dish lines only if Categ.IsChild(it.RefItem) then //Check category of the dish // if (it.RefItem.MainParent.code =11 ) then // if dish from categore of menu and have same code if ((it.State = disOpened) or (it.State = disPrinted)) then if TDish(it).Quantity > 0 then if SL.Count<1 then begin if (TDish(it).Quantity = 0) or (TDish(it).PRListSum = 0) then Price := TDish(it).Price else Price := TDish(it).PRListSum/TDish(it).Quantity; SL.AddObject(FormatFloat('00000000.00', Price) + IntToStr(TDish(it).UNI), TObject(it)); end; end; //Magic q:=0; newsum := 0; aftersum := 0; beforesum := 0; if SYS.ObjectInheritsFrom(AObjectAft, 'TDish') then aftersum := TDish(AObjectAft).PRListSum else aftersum := 0; if SYS.ObjectInheritsFrom(AObjectBef, 'TDish') then beforesum := TDish(AObjectBef).PRListSum else beforesum := 0; // newsum := aftersum-beforesum; newsum := -beforesum; for i:= 0 to SL.Count - 1 do begin a:= 0; d:= TDish(SL.Objects[i]); q:= d.Quantity; if (d.Quantity = 0) or (d.PRListSum = 0) then Price := d.Price else Price := d.PRListSum/d.Quantity; a:= a + Price; // search special discount for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then HaveDisc := HaveDisc + 1; end; if HaveDisc > 0 then topay := RKCheck.CurrentOrder.UnpaidSum + a else topay := RKCheck.CurrentOrder.UnpaidSum; if topay-a+newsum >= limitsum then // if RKCheck.CurrentOrder.UnpaidSum-a+newsum >= limitsum then begin // Delete discount, if a sum changed for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then begin if abs(TDiscountItem(it).CalcAmount) = a then a := 0 else begin RKCheck.DeleteCheckItem(it); end; break; end; end; // Create discount to a dish if a > 0 then begin CheckView.GotoItem(TObject(d)); RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), FloatToStr(a)); end; end else begin // Delete discount, if a sum changed for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then begin RKCheck.DeleteCheckItem(it); break; end; end; end; end; finally SL.Free(); if CurItem <> Nil then CheckView.GotoItem(CurItem); end; RKCheck.CurrentOrder.Recalc(); end;
Creating a special offer "Children's Birthdays: 10% Discount + Free pizza"
Task: To arrange the "Children's Birthdays: 10% Discount + Free pizza" special offer.
To do so, set a 100% discount on the pizza category comprising two pizza types, Home Style Pizza and Children's Pizza. If an order contains two items from the pizza category, the 100% discount is applied only to the first one and the second one has the 10% discount.
Solution: Create a script for the Special Offer selector:
procedure ProcessOperation1002452(Parameter: integer); var i, j, numcateg: integer; DiscCode: integer; it, CurItem: TCheckItem; SL: TStringList; a, q, Price: double; d: TDish; CheckView: TCheckView; Categ: TClassificatorGroup; skip: boolean; begin CheckView := TCheckView(GUI.FindComponentByName('CheckView')); if CheckView = Nil then Exit; CurItem := RKCheck.CurrentCheckItem; SL := TStringList.Create; try // Create list of the dishes, sorted by price SL.Sorted := False; DiscCode := 12; // the changeable fixed amount discount on a dish numcateg := 8; // category code for discount for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; Categ := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', numcateg)); if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then //Check dish lines only if Categ.IsChild(it.RefItem) then //Check category of the dish if ((it.State = disOpened) or (it.State = disPrinted)) then if TDish(it).Quantity > 0 then begin if SL.Count<2 then begin if (TDish(it).Quantity = 0) or (TDish(it).PRListSum = 0) then Price := TDish(it).Price else Price := TDish(it).PRListSum/TDish(it).Quantity; SL.AddObject(FormatFloat('00000000.00', Price) + IntToStr(TDish(it).UNI), TObject(it)); end; end; end; q:=0; for i:= 0 to SL.Count - 1 do begin a:= 0; d:= TDish(SL.Objects[i]); q:= d.Quantity; if (d.Quantity = 0) or (d.PRListSum = 0) then Price := d.Price else Price := d.PRListSum/d.Quantity; if i=0 then a:= a + Price; // discount 100 % if i=1 then a:= a + Price*0.1; // discount 10 % begin // Delete discount if the sum changed for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then begin if abs(TDiscountItem(it).CalcAmount) = a then a := 0 else begin RKCheck.DeleteCheckItem(it); end; break; end; end; // Create discount to a dish if a > 0 then begin CheckView.GotoItem(TObject(d)); RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), FloatToStr(a)); end; end; end; finally SL.Free(); if CurItem <> Nil then CheckView.GotoItem(CurItem); end; RKCheck.CurrentOrder.Recalc(); end;
The dish must have the property Adding to the Order – Separate Line for Each Serving.
The script for automatically applying a 10% discount if another category dish in the order has the 100% discount:
procedure DiscountUsage1002444(UsageParameters: TDiscountUsageParameters); var i,j,cntDiscount, DiscountCode: integer; it,it2: TCheckItem; Categ: TClassificatorGroup; begin dbg.dbgprint('script_disc'); // if not RKCheck.Valid then exit; DiscountCode := 12; // code of the discount "100% on a dish" cntDiscount := 0; Categ := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', 8)); // category code for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then if TDish(it).Quantity > 0 then if Categ.IsChild(it.RefItem) then //Check category of the dish Begin dbg.dbgprint('script_disc 1_'); dbg.dbgprint('cnt = '+inttostr(RKCheck.CheckItemCount(TObject(TDish(it).Discounts)))); for j := RKCheck.CheckItemCount(TObject(TDish(it).Discounts)) - 1 downto 0 do begin it2 := RKCheck.CheckItemByNumber(TObject(TDish(it).Discounts), j); if (it2.Code = DiscountCode) then // if abs(TDiscountItem(it2).SrcAmount)>0 then begin dbg.dbgprint('script_disc 2'); cntDiscount := cntDiscount + 1; break; end; end; End; end; dbg.dbgprint('cntDiscount = '+inttostr(cntDiscount)); if cntDiscount>0 then UsageParameters.UsageMode := umAuto else UsageParameters.UsageMode := umDeny; end;
Creating a Happy Receipt
Task: To create a script for a happy receipt limited by
- The minimal receipt amount
- The total possible number of receipts. The number of receipts depends on the revenue amount at a given moment, i. e. if the revenue is, for example, 50 000 rubles, the maximum number of happy receipts should be five.
Solution:
- Create a print layout in the user reports and a print view for this layout
- In the Options > User Interface > Forms, add the TReportPanel component to the cash form in the Form editor:
- Specify the previously created print layout in the Behavior > Document property
Enter the script:
procedure ProcessOperation1001035(Parameter: integer); var t1, t2: TdateTime; i,QntHO, MaxQntHappyOrd, DiscCode, DiscId: integer; it: TCheckItem; a,b,MinOrderSum,MaxOrderSum, KasSum: double; c: TVisualComponent; str: string; begin DiscCode := 5; // code discount DiscId := 1001029; // id discount KasSum := 0; c := gui.FindComponentByName('UserReportPanel1'); str := TReportPanel(TObject(c)).Text; // dbg.dbgprint('str = '+str); i:=pos('revenue=',str); if i>0 then begin KasSum := StrToFloat(copy(str,i+8,length(str)-(i+8))); //dbg.dbgprint('KasSum = '+FloatToStr(KasSum)); end; t1:=StrToTime('10:01:00'); // start lottery t2:=StrToTime('23:59:00'); // end lottery MaxOrderSum := 15000; // max sum of order the maximum order amount eligible for a happy receipt MinOrderSum := 1; // min sum of order the minimum order amount eligible for a happy receipt MaxQntHappyOrd := trunc(KasSum / 10); // quantity of happy ordets at shift //dbg.dbgprint('QntHO = '+FloatToStr(QntHO)); //dbg.dbgprint('MaxQntHappyOrd = '+FloatToStr(MaxQntHappyOrd)); QntHO:=RKCheck.GetDiscountCount(DiscId, 0, ''); // id discount if QntHO<MaxQntHappyOrd then if (t1<=Time)and(Time<=t2) then begin // calc sum of order START for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then a := a + TDish(it).PRListSum else if SYS.ObjectInheritsFrom(TObject(it), 'TChargeLine') then a := a + TChargeLine(it).CalcAmount; // if it.CODE in [5502, 1003] then // b := b + TDish(it).PRListSum; end; // calc sum of order END // dbg.dbgprint('a = '+floattostr(a)); // dbg.dbgprint('random(100) = '+floattostr(random(100))); if a>MinOrderSum then // check condition of minimum ordersum if a<MaxOrderSum then // check condition of maximum ordersum begin if (random(100)>1) then // set the probability of drawing a happy receipt here: 1 is the maximum probability; 99 is the minimum probability begin RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), FloatToStr(100)); // add discount indicate the discount amount instead of 100 // dbg.dbgprint('Congratulations!!! Happy Order!!! var1'); gui.ShowMessage('Congratulations!!! Happy Order!!!'); // RkCheck.GetDiscountCount end else if (QntHO=0) and (StrToInt(FormatDateTime('n',t2-Time))<=10) then // lottery at last time(minutes) when no winners begin if (random(100)>1) then // set the probability of drawing a happy receipt here: 1 is the maximum probability; 99 is the minimum probability begin RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), FloatToStr(100)); // add discount indicate the discount amount instead of 100 // dbg.dbgprint('Congratulations!!! Happy Order!!! var2'); gui.ShowMessage('Congratulations!!! Happy Order!!!'); // RkCheck.GetDiscountCount end; end; end; end; RK7.PostOperation(rkoBalanceReceipt,0); end;
Adding a Dish to the Order When Switching to the Payment Mode
Task: To create a script adding a dish to the order at moment of switching to the payment mode. The process should be as follows: in the Fast Receipt mode, the system checks the order amount once the Order Payment button is pressed. If the order amount is more than or equal to a specified amount, the system displays a message with Yes and No buttons.
If Yes is clicked, the system adds a dish having the NNN code to the order and switches to the payment mode.
If No is clicked, the system switches right away to the payment mode.
Solution: Instead of the standard selector, add the Payment user selector to the fast receipt. Bind the following user operation script to this selector:
procedure ProcessOperation1001304(Parameter: integer); begin if not RKCheck.Valid then exit //important checking else begin if RKCheck.CurrentOrder.UnpaidSum >= 300 then // Order sum checking if GUI.RKMessageDlg('Do You want add bonus dish?', 0, 3, 10000) = 6 then RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(39), '1'); // add dish with code 39 end; RK7.PostOperation(rkoBalanceReceipt, 0); end;
In this script, change 300 to the required amount and replace the 39 code of the added dish with a relevant value.
Dish Locking
Task: To replace the standard Dishes selector so that when a dish code is entered and this selector is pressed, some dishes get locked.
Solution:
procedure ProcessOperation1038483(Parameter: integer); var ed: TObject; begin if not RKCheck.Valid then exit //important checking else begin ed := TObject(gui.FindComponentByName('Editor')); if SYS.ObjectInheritsFrom(TObject(ed), 'TNumEditor') then if (Pos('1001',TNumEditor(ed).Text)>0) or (Pos('1002',TNumEditor(ed).Text)>0) then gui.showmessage('Zapreshennij simvol!!!') else RK7.PerformOperation(rkoCreateDish, StrToInt(TNumEditor(ed).Text)); end; end;
Statuses
TDrawItemState = (disNone, disOpened, disLocked, disFixed, disPrinted, disPartClosed, disClosed, disDeleted);
How to Get the Combo Element Parent in the Script
Take the ComboDishUNI property of a dish and find a dish having that UNI.
In r_Keeper 7.5.5.035 this can be done as follows:
RKCheck.CurrentOrder.Sessions.FindByUNI(TDish(it).ComboDishUNI).
Older versions don't have the FindByUNI function so to find the dish having the required UNI you have to search through all the dishes in the order.
If ((TDish(it).Quantity <> 0) and (TDish(it).IsComboComp)) then //and (Categ5.IsChild(it.RefItem))) begin for j := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it2 := RKCheck.CurrentOrder.Sessions.Lines[j]; if SYS.ObjectInheritsFrom(TObject(it2), 'TDish') then begin If ((TDish(it).ComboDishUNI = TDish(it2).UNI) and (Categ5.IsChild(it2.RefItem))) then begin end; end; end; //TDish(it).ComboDishUNI end;
Adding a Modifier to All Dishes in the Order
Task: To write a script for the selector to add a modifier to all dishes in the order.
Solution:
procedure ProcessOperation1002489(Parameter: integer); var i,j,CntModif:integer; it, CurItem: TCheckItem; CheckView: TCheckView; begin CheckView := TCheckView(GUI.FindComponentByName('CheckView')); if CheckView = Nil then Exit; CurItem := RKCheck.CurrentCheckItem; if Parameter > 0 then try RK7.PerformOperation(rkoHome, 0); while True do begin it := RKCheck.CurrentCheckItem; if TObject(it) = Nil then break; if SYS.ObjectInheritsFrom(TObject(it), 'TPrintCheckItem') then break; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then begin CntModif := 0; for j := 0 to TDish(it).Modifiers.Count - 1 do // checking by modifier begin if (TDish(it).Modifiers.Items[j].Code=Parameter) then CntModif := CntModif + 1; end; if CntModif = 0 then RKCheck.CreateCheckItem(rkrefModifiers, IntToStr(Parameter), '1'); // add modificator end; RK7.PerformOperation(rkoDown, 0); end; finally if CurItem <> Nil then CheckView.GotoItem(CurItem); end; end;
Assign the user operation with the above-mentioned script to selectors and be sure to indicate the code of a relevant modifier in the Parameter for Empty and Parameter properties.
Adding a New Dish to the Order by Pressing the Saved Dish Line and the Quantity Button
Task: When a saved dish item is selected and the Quantity button is pressed, it is required to add a new item to the bottom of the item list. This function was available in r_keeper 6. When the saved dish item is pressed now, the Quantity button is disabled.
Solution:
- Add a script to the operation scripts
- Assign the script to the specific user operation
- Bind the operation to a function button and assign the button to a new selector.
Script:
procedure ProcessOperation1001322(Parameter: integer); var i, code: integer; CurItem: TCheckItem; begin if not RKCheck.Valid then exit //important checking else begin CurItem := RKCheck.CurrentCheckItem; if SYS.ObjectInheritsFrom(TObject(CurItem), 'TDish') then begin code := CurItem.code; RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(code), '1'); // add dish with code 39 end; end; end;
Adding the Quantity Button with the "Plus One Serving of a Saved Dish" Function
Task: to merge the functions of the Quantity and Plus One Serving of a Saved Dish (additional order) buttons
Solution:
procedure ProcessOperation1001322(Parameter: integer); var i, code: integer; CurItem: TCheckItem; ed: TObject; begin if not RKCheck.Valid then exit //important checking else begin CurItem := RKCheck.CurrentCheckItem; if SYS.ObjectInheritsFrom(TObject(CurItem), 'TDish') then begin ed := TObject(gui.FindComponentByName('Editor')); if (TNumEditor(ed).Text='') then begin code := CurItem.code; RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(code), '1'); // add dish with code end else begin RK7.PerformOperation(rkoEditAmount, 0); end; end; end; end;
Quick Payment in Rubles in r_keeper 7
Task: when the Pay in Rubles or Pay buttons are pressed in the quick receipt mode, the cash payment window should open skipping the payment type selection.
Solution:
procedure ProcessOperation1002215(Parameter: integer); begin if not RKCheck.Valid then exit //important checking else begin RK7.PerformRefObject(RK7.FindItemByCode(rkrefCurrencies, 1)); // 1 - currency code end; end;
Checking the Visit Prepayment Balance
Mission: A restaurant operates in the entry card mode via the MSR algorithm. A script is required that can display the visit prepayment balance.
Solution:
procedure ProcessOperation1001537(Parameter: integer); var i: integer; Limit: double; CardCode: string; McrPay: TMcrPay; begin if TObject(RKCheck.CurrentOrder) = Nil then Exit; // Limit calculation Limit := 0; CardCode := ''; for i := 0 to RKCheck.CurrentOrder.Sessions.McrPays.ItemCount - 1 do begin McrPay := TMcrPay(RKCheck.CurrentOrder.Sessions.McrPays.Items[i]); Limit := Limit + McrPay.MaxAmount; CardCode := McrPay.CardNum; end; if CardCode = '' then Exit else gui.Showmessage('Card '+CardCode+' balance '+FloatToStr(Limit)+' р.'); end;
Limiting the 100% Category Discount
Mission: The 100% discount should apply only to one dish item belonging to the category.
Solution:
procedure ProcessOperation1001621(Parameter: integer); var i, j, numcateg: integer; DiscCode: integer; it, CurItem: TCheckItem; SL: TStringList; a, q, Price: double; d: TDish; CheckView: TCheckView; Categ: TClassificatorGroup; skip: boolean; begin CheckView := TCheckView(GUI.FindComponentByName('CheckView')); if CheckView = Nil then Exit; CurItem := RKCheck.CurrentCheckItem; SL := TStringList.Create; try // Create list of the dishes, sorted by price SL.Sorted := True; DiscCode := 11; numcateg := 8; //5 - category code for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; Categ := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', numcateg)); //5 - category code if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then //Check dish lines only if Categ.IsChild(it.RefItem) then //Check category of the dish // if (it.RefItem.MainParent.code =11 ) then // if dish from category of menu and have same code if ((it.State = disOpened) or (it.State = disPrinted)) then begin skip := false; for j:=0 to SL.Count - 1 do begin d:= TDish(SL.Objects[j]); if d.code=it.code then Skip := True; end; if not(skip) then begin if (TDish(it).Quantity = 0) or (TDish(it).PRListSum = 0) then Price := TDish(it).Price else Price := TDish(it).PRListSum/TDish(it).Quantity; SL.AddObject(FormatFloat('00000000.00', Price) + IntToStr(TDish(it).UNI), TObject(it)); end; end; end; //Magic q:=0; for i:= 0 to SL.Count - 1 do begin a:= 0; d:= TDish(SL.Objects[i]); q:= d.Quantity; if (d.Quantity = 0) or (d.PRListSum = 0) then Price := d.Price else Price := d.PRListSum/d.Quantity; a:= a + Price; // Delete discount if the sum changed for j := RKCheck.CheckItemCount(TObject(d.Discounts)) - 1 downto 0 do begin it := RKCheck.CheckItemByNumber(TObject(d.Discounts), j); if (it.Code = DiscCode) then begin if abs(TDiscountItem(it).SrcAmount) = a then a := 0 else RKCheck.DeleteCheckItem(it); break; end; end; // Create discount to a dish if a > 0 then begin CheckView.GotoItem(TObject(d)); RKCheck.CreateCheckItem(rkrefDiscounts, IntToStr(DiscCode), FloatToStr(a)); end; end; finally SL.Free(); if CurItem <> Nil then CheckView.GotoItem(CurItem); end; RKCheck.CurrentOrder.Recalc(); end;
Opening the Browser Window for Displaying Cash Operation Reports
Task: To create a function button in the main cash menu, pressing which will execute the command: fsWeb.exe "https://172.22.4.57:8088/csthtm/overall1.html", where 172.22.4.57 is the value of an extended restaurant property
Solution:
procedure ProcessOperation1001763(Parameter: integer); var s: string; begin // TRK7Restaurant(RK7.CashGroup.MainParent).genMessage_Addon_49='1' s := TRK7Restaurant(RK7.CashGroup.MainParent).genTEL; GUI.CmdExec('fsWeb.exe "https://'+s+':8088/csthtm/overall1.html"'); end;
Assign the script to the user operation that, in its turn, should be assigned to a function button.
Adding a Dish to the Order
Task: After swiping a discount card, a discount and a gift — a dish with a specified code — should be awarded to the customer card.
The process should be as follows:
- Creating a button in the interface
- Once this button is pressed, a customer enters a promo code
- This promo code is read as the card code, there is a corresponding MCR algorithm written for it
- FarCards is called, a discount and a free dish are received. It can be indicated in some field.
- This dish is added to a table and the discount is applied to it.
Solution:
Create the script:
procedure ProcessOperation1001765(Parameter: integer); var ed: TObject; DeviceID : integer; begin if not RKCheck.Valid then exit //important checking else begin DeviceID := 0; // PDS interface ID ed := TObject(gui.FindComponentByName('Editor')); if SYS.ObjectInheritsFrom(TObject(ed), 'TNumEditor') then if (Pos('1001',TNumEditor(ed).Text)>0) or (Pos('1002',TNumEditor(ed).Text)>0) then gui.showmessage('nevernii promokod!!!') else RK7.PerformMCRAlgorith('8989='+TNumEditor(ed).Text, DeviceID); //RK7.PerformOperation(rkoCreateDish, StrToInt(TNumEditor(ed).Text)); end; end;
In the input field of the cash terminal, a promotional code is entered. In our example, it is 1001 or 1002. If the entered promotional code matches the one stored in the script, the MCR script is called.
The MCR script needs to be created with the following properties:
Main > Area: Discount
Main > Object: Discount Used
General > Device Types > Script: enabled.
function MCR1001146(DeviceSignal: Integer; DeviceIdent: Integer; var Parameter: String): Boolean; var RestCode: integer; begin Result := False; if pos('8989=', Parameter) = 1 then begin RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(43), '1'); // adding the dish with code 43 to the order Result := True; end; end;
Checking the number of dishes from a certain category
Task: to create a script to check the number of dishes from a certain category.
Solution:
procedure ProcessOperation1001742(Parameter: integer); var i, CategCode: integer; it: TCheckItem; iQnt : double; Categ: TClassificatorGroup; CurSession: TOrderSession; begin if (not RKCheck.Valid) then exit; else begin CategCode := 8; //category code iQnt := 0; Categ := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', CategCode));//category code if SYS.ObjectInheritsFrom(TObject(RKCheck.CurrentCheckItem), 'TDish') then CurSession := TDish(RKCheck.CurrentCheckItem).Session; for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then begin if CurSession = TDish(it).Session then if (Categ.IsChild(it.RefItem)) then iQnt := iQnt + Trunc(TDish(it).Quantity); end; end; //RKCheck.CurrentOrder.Visit.GuestCnt if (iQnt < 4) then begin GUI.Showmessage('Chua du? diê`u kiê?n a´p du?ng: ' + FloatToStr(iQnt)); Exit; end; end; end;
Creating Additional Reports When Closing a Shift
Task: to create a script to automatically generate additional reports when a shift is closed.
Solution:
procedure ProcessOperation1001784(Parameter: integer); begin RK7.PerformRefObject( RK7.FindItemByCode(rkrefMaketSchemeDetails, 184) ); // document view code in the printing schemes RK7.PerformOperation(rkoMMCloseCommonShift, 0); // common shift closing end;
Forbidding to Cancel the Bill in One Order More Than X Times
Task: It is necessary to forbid canceling the guest bill in one order more than X times, specified in the parameter.
-1 (default) — allowed to cancel unlimited number of times
0 — it is forbidden to cancel the guest bill at all
1...999 — indicates how many times you can cancel the guest bill in an order/visit
Order >> print pre-check >> cancel pre-check >> print pre-check again >> can not cancel pre-check (system warning and must not allow).
The superuser can always cancel receipts without paying attention to this parameter.
Solution:
- Create the MaxDelBillCnt extended property of the integer type and assign it to the restaurant
- In the properties of the restaurant, specify a value for this property
- Create a script:
procedure ProcessOperation1002346(Parameter: integer); var i, CntDelBill, MaxDelBillCnt: integer; it: TCheckItem; begin CntDelBill := 0; MaxDelBillCnt := -1; // if ( TRK7Restaurant(RK7.CashGroup.MainParent).genMaxDelBillCnt=1) then MaxDelBillCnt := TRK7Restaurant(RK7.CashGroup.MainParent).genMaxDelBillCnt; if MaxDelBillCnt = -1 then RK7.PerformOperation(RkoUnlockBill,0); if MaxDelBillCnt = 0 then begin gui.showmessage('Cancel bill forbidden!'); Exit; end; if MaxDelBillCnt > 0 then begin for i := 0 to RKCheck.CurrentOrder.Sessions.LinesCount - 1 do begin it := RKCheck.CurrentOrder.Sessions.Lines[i]; if SYS.ObjectInheritsFrom(TObject(it), 'tPrintCheckItem') then if tPrintCheckItem(it).IsBill then if tPrintCheckItem(it).Deleted then CntDelBill := CntDelBill + 1; end; if CntDelBill >= MaxDelBillCnt then begin if RK7.PerformOperation(rkoUser15, 0)=1 then RK7.PerformOperation(RkoUnlockBill,0) else gui.showmessage('Cancel bill forbidden!'); end else RK7.PerformOperation(RkoUnlockBill,0); end; dbg.dbgprint('CntDelBill = ' + IntToStr(CntDelBill)); dbg.dbgprint('MaxDelBillCnt = ' + IntToStr(MaxDelBillCnt)); end;
Assign an empty script to user operation 15:
procedure ProcessOperation1001624(Parameter: integer); begin end;
Enable the access control for this operation. Give the superuser the right for the operation.
Using Different Price Types
Task: when selling dishes at the cash register to a regular customer, not authorized at the cash register with a card, the price should be Price Type No. 1. When selling dishes to a restaurant customer, authorized with a card at the cash register, the price should be Price Type No. 2.
Solution:
procedure ProcessOperation1001986(Parameter: integer); var Props: TVisitOrderInfo; begin Props := TVisitOrderInfo.Create(); try Props.OrderCategoryID := 10033; // specify the order category ID RKCheck.UpdateOrderProps(Props); finally Props.Free; end; end;
For version r_keeper 7.5.4.x, enable the Change order category after creation option.
Changing the Main Waiter
Task: to create a script to change the main waiter.
Solution:
procedure ProcessOperation1000813(Parameter: integer); var Props: TVisitOrderInfo; begin Props := TVisitOrderInfo.Create; try Props.MainWaiterID := RK7.FindItemByCode(rkrefEmployees, 21).Ident; RKCheck.UpdateOrderProps(Props); finally Props.Free; end; end;
Changing the Price Type by Setting the Order of Serving Dishes
Task: to create a script that sets serving order No. 1 for dishes of a specified category, and serving order No. 2 for all other dishes.
Solution:
procedure ProcessOperation1002417(Parameter: integer); var CategCode, course1, course2: integer; Categ: TClassificatorGroup; it: TCheckItem; begin if not RKCheck.Valid then exit //important checking else begin CategCodeList := TStringList.Create; //********** Set parameters ***********// CategCode := 27; // code of category 1 course1 := 1002378; // serving order 1 ID course2 := 1002379; // serving order 2 ID //********** Set parameters ***********// Categ := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', CategCode));//category code while True do begin it := RKCheck.CurrentCheckItem; if TObject(it) = Nil then break; if SYS.ObjectInheritsFrom(TObject(it), 'TPrintCheckItem') then break; if SYS.ObjectInheritsFrom(TObject(it), 'TDish') then if (Categ.IsChild(TDish(it).RefItem)) then // checking category of dish // if TRK7MenuItem(RK7.FindItemBySifr(rkrefMenuItems, TDish(it).Sifr)).genAstor_code = '1' then // check ext property RK7.PerformOperation(rkoMoveCurrentDishToSes, course1); // ident of course else RK7.PerformOperation(rkoMoveCurrentDishToSes, course2); // ident of course; RK7.PerformOperation(rkoDown, 0); end; end; end;
Changing the Amount Discount
Task: The discount is tied to the card and works for orders with delivery. Every tenth order should receive a discount of 500 rubles, provided that the average receipt for these 10 orders was at least 500 rubles.
Solution:
procedure ProcessOperation1001902(Parameter: integer); var ed: TObject; it: TCheckItem; begin RK7.PerformOperation(rkoHome, 0); while True do begin it := RKCheck.CurrentCheckItem; if TObject(it) = Nil then break; if SYS.ObjectInheritsFrom(TObject(it), 'TPrintCheckItem') then break; if SYS.ObjectInheritsFrom(TObject(it), 'TDiscountItem') then if TDiscountItem(it).Code = 14 then // specify the discount code if (it.State = disOpened) then // checking the unsaved status of the discount begin ed := TObject(gui.FindComponentByName('Editor')); if SYS.ObjectInheritsFrom(TObject(ed), 'TNumEditor') then begin TNumEditor(ed).Text := IntToStr(trunc(100)); RK7.PerformOperation(rkoEditOpenPrice, 0); end; TNumEditor(ed).Text := ''; end; RK7.PerformOperation(rkoDown, 0); end; end;
Change the Combo or Dish Size When Pressing a Button
Task: To write a script and make buttons, when pressing which the dish size will change.
Solution:
A script for enlarging the size:
procedure ProcessOperation1002094(Parameter: integer); var NextCateg,Categ1,Categ2, Classif1,Classif2: TClassificatorGroup; it, CurItem: TCheckItem; cv: TObject; mi_d,mi_s: trk7menuitem; ex,i,j,MinSize,MaxSize,ClassifCode1,ClassifCode2,CurSize,NextSize,NextCategCode: integer; begin if not RKCheck.Valid then exit //important checking else begin MinSize := 1; MaxSize := 3; CurItem := RKCheck.CurrentCheckItem; ClassifCode1 := 16; // code classificator of dish type ClassifCode2 := 9; // code classificator of dish size if SYS.ObjectInheritsFrom(TObject(CurItem), 'TDish') then // if current item is dish if not TDish(CurItem).IsComboComp then // comment this line if need allow change size for combo-components begin // dbg.dbgprint('dish type'); Classif1 := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', ClassifCode1)); // dbg.dbgprint(inttoStr(Classif1.ChildCount)); for i := 0 to Classif1.ChildCount - 1 do begin Categ1 := TClassificatorGroup(Classif1.ChildItem(i)); if Categ1.IsChild(CurItem.RefItem) then begin // dbg.dbgprint('Classif1.code='+IntToStr(Classif1.code)+' Categ1.code='+IntToStr(Categ1.code)); break; end; end; // dbg.dbgprint('dish size'); Classif2 := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', ClassifCode2)); // dbg.dbgprint(inttoStr(Classif2.ChildCount)); for i := 0 to Classif2.ChildCount - 1 do begin Categ2 := TClassificatorGroup(Classif2.ChildItem(i)); if Categ2.IsChild(CurItem.RefItem) then begin CurSize := Categ2.SortOrder; // dbg.dbgprint('Classif2.code='+IntToStr(Classif2.code)+' Categ2.code='+IntToStr(Categ2.code)+' SortOrder='+IntToStr(Categ2.SortOrder)); break; end; end; NextSize := CurSize + 1; if NextSize > MaxSize then begin //************for recursy change size **************/ // NextSize := MinSize; // uncomment this recursion to resize //************for recursy change size **************/ gui.showmessage('reached a maximum size dishes!'); // comment out this recursion to resize exit; // comment out this recursion to resize end; // dbg.dbgprint('serch dish size'); Classif2 := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', ClassifCode2)); // dbg.dbgprint(inttoStr(Classif2.ChildCount)); for i := 0 to Classif2.ChildCount - 1 do begin Categ2 := TClassificatorGroup(Classif2.ChildItem(i)); if Categ2.SortOrder=NextSize then begin NextCategCode := Categ2.Code; NextCateg := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', NextCategCode)); // dbg.dbgprint('Classif2.code='+IntToStr(Classif2.code)+' Categ2.code='+IntToStr(Categ2.code)+' SortOrder='+IntToStr(Categ2.SortOrder)); break; end; end; // dbg.dbgprint('serch dish type size'); ex := 0; for i := 0 to Categ1.ChildCount - 1 do begin mi_d := trk7menuitem(Categ1.ChildItem(i)); // dbg.dbgprint(inttostr(mi_d.code)+' '+mi_d.RightLangName+' '+inttostr(mi_d.extcode)+' '+inttostr(Categ1.SortOrder)+' '+(mi_d.name)+' '); for j := 0 to Categ2.ChildCount - 1 do begin mi_s := trk7menuitem(NextCateg.ChildItem(j)); if mi_d.code = mi_s.code then begin RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(mi_s.code), FloatToStr(TDish(CurItem).Quantity)); if CurItem <> Nil then begin cv := TObject(gui.FindComponentByName('CheckView')); if SYS.ObjectInheritsFrom(TObject(cv), 'TCheckView') then TCheckView(cv).GotoItem(CurItem); end; // dbg.dbgprint('BINGO '+inttostr(mi_s.ident)+inttostr(mi_s.code)+' '+mi_s.RightLangName+' '+inttostr(mi_s.extcode)+' '+inttostr(NextCateg.SortOrder)+' '+(mi_s.name)+' '); ex := 1; break; end; end; if ex > 0 then break; end; end; end; end;
A script for reducing the size:
procedure ProcessOperation1002112(Parameter: integer); var NextCateg,Categ1,Categ2, Classif1,Classif2: TClassificatorGroup; it, CurItem: TCheckItem; cv: TObject; mi_d,mi_s: trk7menuitem; ex,i,j,MinSize,MaxSize,ClassifCode1,ClassifCode2,CurSize,PrevSize,NextCategCode: integer; begin if not RKCheck.Valid then exit //important checking else begin MinSize := 1; MaxSize := 3; CurItem := RKCheck.CurrentCheckItem; ClassifCode1 := 16; // code classificator of dish type ClassifCode2 := 9; // code classificator of dish size if SYS.ObjectInheritsFrom(TObject(CurItem), 'TDish') then // if current item is dish if not TDish(CurItem).IsComboComp then // comment this line if need allow change size for combo-components begin // dbg.dbgprint('dish type'); Classif1 := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', ClassifCode1)); // dbg.dbgprint(inttoStr(Classif1.ChildCount)); for i := 0 to Classif1.ChildCount - 1 do begin Categ1 := TClassificatorGroup(Classif1.ChildItem(i)); if Categ1.IsChild(CurItem.RefItem) then begin // dbg.dbgprint('Classif1.code='+IntToStr(Classif1.code)+' Categ1.code='+IntToStr(Categ1.code)); break; end; end; // dbg.dbgprint('dish size'); Classif2 := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', ClassifCode2)); // dbg.dbgprint(inttoStr(Classif2.ChildCount)); for i := 0 to Classif2.ChildCount - 1 do begin Categ2 := TClassificatorGroup(Classif2.ChildItem(i)); if Categ2.IsChild(CurItem.RefItem) then begin CurSize := Categ2.SortOrder; // dbg.dbgprint('Classif2.code='+IntToStr(Classif2.code)+' Categ2.code='+IntToStr(Categ2.code)+' SortOrder='+IntToStr(Categ2.SortOrder)); break; end; end; PrevSize := CurSize - 1; if PrevSize < MinSize then begin //************for recursy change size **************/ // PrevSize := MaxSize; // uncomment this recursion to resize //************for recursy change size **************/ gui.showmessage('reached a minimum size dishes!'); // comment out this recursion to resize exit; // comment out this recursion to resize end; // dbg.dbgprint('serch dish size'); Classif2 := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', ClassifCode2)); // dbg.dbgprint(inttoStr(Classif2.ChildCount)); for i := 0 to Classif2.ChildCount - 1 do begin Categ2 := TClassificatorGroup(Classif2.ChildItem(i)); if Categ2.SortOrder=PrevSize then begin NextCategCode := Categ2.Code; NextCateg := TClassificatorGroup(getitemBycodeNum('ClassificatorGroups', NextCategCode)); // dbg.dbgprint('Classif2.code='+IntToStr(Classif2.code)+' Categ2.code='+IntToStr(Categ2.code)+' SortOrder='+IntToStr(Categ2.SortOrder)); break; end; end; // dbg.dbgprint('serch dish type size'); ex := 0; for i := 0 to Categ1.ChildCount - 1 do begin mi_d := trk7menuitem(Categ1.ChildItem(i)); // dbg.dbgprint(inttostr(mi_d.code)+' '+mi_d.RightLangName+' '+inttostr(mi_d.extcode)+' '+inttostr(Categ1.SortOrder)+' '+(mi_d.name)+' '); for j := 0 to Categ2.ChildCount - 1 do begin mi_s := trk7menuitem(NextCateg.ChildItem(j)); if mi_d.code = mi_s.code then begin RKCheck.CreateCheckItem(rkrefMenuItems, IntToStr(mi_s.code), FloatToStr(TDish(CurItem).Quantity)); if CurItem <> Nil then begin cv := TObject(gui.FindComponentByName('CheckView')); if SYS.ObjectInheritsFrom(TObject(cv), 'TCheckView') then TCheckView(cv).GotoItem(CurItem); end; // dbg.dbgprint('BINGO '+inttostr(mi_s.ident)+inttostr(mi_s.code)+' '+mi_s.RightLangName+' '+inttostr(mi_s.extcode)+' '+inttostr(NextCateg.SortOrder)+' '+(mi_s.name)+' '); ex := 1; break; end; end; if ex > 0 then break; end; end; end; end;