adding offers examples Change-Id: I9f8bd2bad35ba9aa5e3ad86fe1a03fd2d27b4e9d
diff --git a/offers/dining/go/offerFeedGenerator.go b/offers/dining/go/offerFeedGenerator.go new file mode 100644 index 0000000..14adfbd --- /dev/null +++ b/offers/dining/go/offerFeedGenerator.go
@@ -0,0 +1,125 @@ +package main + +import ( + pb "feed/app/generated/ext/maps/booking/offers/proto" + "fmt" + "log" + + money "google.golang.org/genproto/googleapis/type/money" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + dayofweek "google.golang.org/genproto/googleapis/type/dayofweek" + timeofday "google.golang.org/genproto/googleapis/type/timeofday" + proto "google.golang.org/protobuf/proto" + + "google.golang.org/protobuf/encoding/protojson" +) + +func main() { + // 200 MB feed file size limit + const MaxBytesDataFile = 200 * 1024 * 1024 + + // Create OfferFeed with offers + feed := &pb.OfferFeed{} + + // Build the offers + offer := &pb.Offer{ + OfferId: "offer-1", + EntityIds: []string{"dining-1"}, + OfferSource: pb.OfferSource_OFFER_SOURCE_AGGREGATOR, + ActionType: pb.ActionType_ACTION_TYPE_DINING, + OfferModes: []pb.OfferMode{ + pb.OfferMode_OFFER_MODE_WALK_IN, + pb.OfferMode_OFFER_MODE_FREE_RESERVATION, + }, + OfferCategory: pb.OfferCategory_OFFER_CATEGORY_BASE_OFFER, + OfferDetails: &pb.OfferDetails{ + OfferDisplayText: "₹100 off on your order", + OfferSpecification: &pb.OfferDetails_DiscountValue{ + DiscountValue: &money.Money{ + CurrencyCode: "INR", + Units: 100, + }, + }, + }, + OfferRestrictions: &pb.OfferRestrictions{ + CombinableWithOtherOffers: true, + CombinableOfferCategories: []pb.OfferCategory{ + pb.OfferCategory_OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER, + pb.OfferCategory_OFFER_CATEGORY_ADD_ON_COUPON_OFFER, + }, + }, + Terms: &pb.Terms{ + RestrictedToCertainUsers: false, + TermsAndConditions: "Valid on all menu items.", + }, + ValidityPeriods: []*pb.ValidityPeriod{ + { + ValidPeriod: &pb.ValidityRange{ + ValidFromTime: ×tamppb.Timestamp{Seconds: 1687062000}, + ValidThroughTime: ×tamppb.Timestamp{Seconds: 1956556800}, + }, + TimeOfDay: []*pb.TimeOfDayWindow{ + // Monday - Thursday Window + { + TimeWindows: &pb.TimeOfDayRange{ + OpenTime: &timeofday.TimeOfDay{Hours: 13}, + CloseTime: &timeofday.TimeOfDay{Hours: 23}, + }, + DayOfWeek: []dayofweek.DayOfWeek{ + dayofweek.DayOfWeek_MONDAY, + dayofweek.DayOfWeek_TUESDAY, + dayofweek.DayOfWeek_WEDNESDAY, + dayofweek.DayOfWeek_THURSDAY, + }, + }, + // Friday - Sunday Window + { + TimeWindows: &pb.TimeOfDayRange{ + OpenTime: &timeofday.TimeOfDay{Hours: 13}, + CloseTime: &timeofday.TimeOfDay{ + Hours: 23, + Minutes: 59, + Seconds: 59, + }, + }, + DayOfWeek: []dayofweek.DayOfWeek{ + dayofweek.DayOfWeek_FRIDAY, + dayofweek.DayOfWeek_SATURDAY, + dayofweek.DayOfWeek_SUNDAY, + }, + }, + }, + }, + }, + OfferUrl: "https://www.example-restaurant.com/offer/base_offer_1", + ImageUrl: "https://www.example-restaurant.com/images/offer_base.jpg", + } + + // Example testing for feed size + // Protocol buffer message must be less than 2 GiB + // https://protobuf.dev/programming-guides/proto-limits/ + // It is recommended to not exceed 200 MB, as there is an Actions + // Center limit of 200 MB per file after compression. + offerSize := proto.Size(offer) + currentFeedSize := proto.Size(feed) + + if currentFeedSize + offerSize < MaxBytesDataFile { + feed.Data = append(feed.Data, offer) + } else { + // 1. Serialize and save the current 'feed' to a file + // 2. Reset 'feed' to a new empty OfferFeed + // 3. Add the 'offer' to the new feed + } + + // Serialize to JSON + marshaler := protojson.MarshalOptions{ + UseProtoNames: true, + } + + jsonOutput, err := marshaler.Marshal(feed) + if err != nil { + log.Fatalf("Failed to marshal feed: %v", err) + } + + fmt.Println(string(jsonOutput)) +} \ No newline at end of file
diff --git a/offers/dining/java/pom.xml b/offers/dining/java/pom.xml new file mode 100644 index 0000000..53708e1 --- /dev/null +++ b/offers/dining/java/pom.xml
@@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>com.example.offers</groupId> + <artifactId>feed</artifactId> + <version>1.0.0</version> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <java.version>21.0</java.version> + <maven.compiler.source>21</maven.compiler.source> + <maven.compiler.target>21</maven.compiler.target> + <protobuf.version>4.29.3</protobuf.version> + </properties> + <dependencies> + <dependency> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java</artifactId> + <version>${protobuf.version}</version> + </dependency> + <dependency> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java-util</artifactId> + <version>${protobuf.version}</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.2.2</version> + <configuration> + <archive> + <manifest> + <addClasspath>true</addClasspath> + </manifest> + </archive> + </configuration> + </plugin> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + <archive> + <manifest> + <mainClass>com.example.offers.OfferFeedGenerator</mainClass> + </manifest> + </archive> + </configuration> + <executions> + <execution> + <id>make-assembly</id> <!-- this is used for inheritance merges --> + <phase>package</phase> <!-- bind to the packaging phase --> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>io.github.ascopes</groupId> + <artifactId>protobuf-maven-plugin</artifactId> + <configuration> + <protoc>${protobuf.version}</protoc> + </configuration> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project>
diff --git a/offers/dining/java/src/main/java/com/example/offers/OfferFeedGenerator.java b/offers/dining/java/src/main/java/com/example/offers/OfferFeedGenerator.java new file mode 100644 index 0000000..75db6fd --- /dev/null +++ b/offers/dining/java/src/main/java/com/example/offers/OfferFeedGenerator.java
@@ -0,0 +1,105 @@ +package com.example.offers; + +import com.google.protobuf.util.JsonFormat; +import ext.maps.booking.feeds.offers.Offer; +import ext.maps.booking.feeds.offers.OfferFeed; +import ext.maps.booking.feeds.offers.OfferDetails; +import ext.maps.booking.feeds.offers.OfferRestrictions; +import ext.maps.booking.feeds.offers.Terms; +import ext.maps.booking.feeds.offers.ValidityPeriod; +import ext.maps.booking.feeds.offers.ValidityRange; +import ext.maps.booking.feeds.offers.OfferCategory; +import ext.maps.booking.feeds.offers.OfferMode; +import ext.maps.booking.feeds.offers.OfferSource; +import ext.maps.booking.feeds.offers.ActionType; +import ext.maps.booking.feeds.offers.TimeOfDayWindow; +import ext.maps.booking.feeds.offers.TimeOfDayRange; + +import com.google.type.Money; +import com.google.protobuf.Timestamp; +import com.google.type.DayOfWeek; +import com.google.type.TimeOfDay; + + +public class OfferFeedGenerator { + + // 200 MB + public static final int MAX_BYTES_DATA_FILE = 200 * 1024 * 1024; + + public static void main(String[] args) throws Exception { + + // Create OfferFeed + OfferFeed.Builder feed = OfferFeed.newBuilder(); + + // Build the offers + Offer offer = Offer.newBuilder() + .setOfferId("offer-1") + .addEntityIds("dining-1") + .setOfferSource(OfferSource.OFFER_SOURCE_AGGREGATOR) + .setActionType(ActionType.ACTION_TYPE_DINING) + .addOfferModes(OfferMode.OFFER_MODE_WALK_IN) + .addOfferModes(OfferMode.OFFER_MODE_FREE_RESERVATION) + .setOfferCategory(OfferCategory.OFFER_CATEGORY_BASE_OFFER) + .setOfferDetails(OfferDetails.newBuilder() + .setOfferDisplayText("₹100 off on your order") + .setDiscountValue(Money.newBuilder() + .setCurrencyCode("INR") + .setUnits(100))) + .setOfferRestrictions(OfferRestrictions.newBuilder() + .setCombinableWithOtherOffers(true) + .addCombinableOfferCategories(OfferCategory.OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER) + .addCombinableOfferCategories(OfferCategory.OFFER_CATEGORY_ADD_ON_COUPON_OFFER)) + .setTerms(Terms.newBuilder() + .setRestrictedToCertainUsers(false) + .setTermsAndConditions("Valid on all menu items.")) + .addValidityPeriods(ValidityPeriod.newBuilder() + .setValidPeriod(ext.maps.booking.feeds.offers.ValidityRange.newBuilder() + .setValidFromTime(Timestamp.newBuilder().setSeconds(1687062000)) + .setValidThroughTime(Timestamp.newBuilder().setSeconds(1956556800))) + // // Monday - Thursday Window + .addTimeOfDay(ext.maps.booking.feeds.offers.TimeOfDayWindow.newBuilder() + .setTimeWindows(ext.maps.booking.feeds.offers.TimeOfDayRange.newBuilder() + .setOpenTime(com.google.type.TimeOfDay.newBuilder().setHours(13)) + .setCloseTime(com.google.type.TimeOfDay.newBuilder().setHours(23))) + .addDayOfWeek(DayOfWeek.MONDAY) + .addDayOfWeek(DayOfWeek.TUESDAY) + .addDayOfWeek(DayOfWeek.WEDNESDAY) + .addDayOfWeek(DayOfWeek.THURSDAY)) + // Friday - Sunday Window + .addTimeOfDay(ext.maps.booking.feeds.offers.TimeOfDayWindow.newBuilder() + .setTimeWindows(ext.maps.booking.feeds.offers.TimeOfDayRange.newBuilder() + .setOpenTime(com.google.type.TimeOfDay.newBuilder().setHours(13)) + .setCloseTime(com.google.type.TimeOfDay.newBuilder().setHours(23).setMinutes(59).setSeconds(59))) + .addDayOfWeek(DayOfWeek.FRIDAY) + .addDayOfWeek(DayOfWeek.SATURDAY) + .addDayOfWeek(DayOfWeek.SUNDAY)) + ) + .setOfferUrl("https://www.example-restaurant.com/offer/base_offer_1") + .setImageUrl("https://www.example-restaurant.com/images/offer_base.jpg") + .build(); + + + // Example testing for offer feed size + // Protocol buffer message must be less than 2 GiB + // https://protobuf.dev/programming-guides/proto-limits/ + // It is recommended to not exceed 200 MB, as there is an Actions + // Center limit of 200 MB per file after compression. + int offerSize = offer.getSerializedSize(); + int currentFeedSize = feed.build().getSerializedSize(); + + if (currentFeedSize + offerSize < MAX_BYTES_DATA_FILE) { + feed.addData(offer); + } else { + // 1. Serialize and save the current 'feed' to a file + // 2. Reset 'feed' to a new empty OfferFeed + // 3. Add the 'offer' to the new feed + } + + // Serialize to JSON + String jsonOutput = JsonFormat.printer() + .preservingProtoFieldNames() + .print(feed); + + System.out.println(jsonOutput); + } +}
diff --git a/offers/dining/python/offer_feed.py b/offers/dining/python/offer_feed.py new file mode 100644 index 0000000..8f50f53 --- /dev/null +++ b/offers/dining/python/offer_feed.py
@@ -0,0 +1,106 @@ +import json +from google.protobuf.json_format import MessageToDict +from google.protobuf.timestamp_pb2 import Timestamp + + +# Replace these imports with your actual generated proto package paths +from generated import offer_pb2 +from generated import money_pb2 +from generated import dayofweek_pb2 +from generated import timeofday_pb2 + +_MAX_BYTES_DATA_FILE = 200 * 1024 * 1024 + +def generate_offer_feed(): + + # Create OfferFeed + feed = offer_pb2.OfferFeed() + + # Build the offers + offer = offer_pb2.Offer( + offer_id="offer-1", + entity_ids=["dining-1"], + offer_source=offer_pb2.OFFER_SOURCE_AGGREGATOR, + action_type=offer_pb2.ACTION_TYPE_DINING, + offer_modes=[ + offer_pb2.OFFER_MODE_WALK_IN, + offer_pb2.OFFER_MODE_FREE_RESERVATION + ], + offer_category=offer_pb2.OFFER_CATEGORY_BASE_OFFER, + offer_details=offer_pb2.OfferDetails( + offer_display_text="₹100 off on your order", + # Note: If this is a 'oneof', you set the field name directly + discount_value=money_pb2.Money( + currency_code="INR", + units=100 + ) + ), + offer_restrictions=offer_pb2.OfferRestrictions( + combinable_with_other_offers=True, + combinable_offer_categories=[ + offer_pb2.OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER, + offer_pb2.OFFER_CATEGORY_ADD_ON_COUPON_OFFER + ] + ), + terms=offer_pb2.Terms( + restricted_to_certain_users=False, + terms_and_conditions="Valid on all menu items." + ), + validity_periods=[ + offer_pb2.ValidityPeriod( + valid_period=offer_pb2.ValidityRange( + valid_from_time=Timestamp(seconds=1687062000), + valid_through_time=Timestamp(seconds=1956556800) + ), + time_of_day=[ + # Monday - Thursday Window + offer_pb2.TimeOfDayWindow( + time_windows=offer_pb2.TimeOfDayRange( + open_time=timeofday_pb2.TimeOfDay(hours=13), + close_time=timeofday_pb2.TimeOfDay(hours=23) + ), + day_of_week=[ + dayofweek_pb2.DayOfWeek.MONDAY, + dayofweek_pb2.DayOfWeek.TUESDAY, + dayofweek_pb2.DayOfWeek.WEDNESDAY, + dayofweek_pb2.DayOfWeek.THURSDAY + ] + ), + # Friday - Sunday Window + offer_pb2.TimeOfDayWindow( + time_windows=offer_pb2.TimeOfDayRange( + open_time=timeofday_pb2.TimeOfDay(hours=13), + close_time=timeofday_pb2.TimeOfDay(hours=23, minutes=59, seconds=59) + ), + day_of_week=[ + dayofweek_pb2.DayOfWeek.FRIDAY, + dayofweek_pb2.DayOfWeek.SATURDAY, + dayofweek_pb2.DayOfWeek.SUNDAY + ] + ) + ] + ) + ], + offer_url="https://www.example-restaurant.com/offer/base_offer_1", + image_url="https://www.example-restaurant.com/images/offer_base.jpg" + ) + + # Example testing for menu feed size + # Protocol buffer message must be less than 2 GiB + # https://protobuf.dev/programming-guides/proto-limits/ + # It is recommended to not exceed 200 MB, as there is an Actions + # Center limit of 200 MB per file after compression. + if feed.ByteSize() + offer.ByteSize() < _MAX_BYTES_DATA_FILE: + feed.data.append(offer) + # else write current feed to file and start a new feed + + # Serialize to JSON + # preserving_proto_field_names=True ensures camelCase becomes snake_case if defined that way in .proto + json_output = json.dumps( + MessageToDict(feed, preserving_proto_field_name=True) + ) + + print(json_output) + +if __name__ == "__main__": + generate_offer_feed() \ No newline at end of file