Giter Club home page Giter Club logo

festival-tickets-sale's Introduction

FESTIVAL TICKETS SALE

OVERVIEW

This app aims at being a useful sales point for selling access tickets for a festival, or any other event.
It could also sell any other items, such as the following examples:

  • Excursion packs
  • Online courses
  • Online private lesson packs

The app is linked to a Spreadsheet, which can be customized to change the following values, which will be reflected on the app, making the app fully reusable:

  • Items' names

  • Items' codes

  • Items' pricing

  • Items' details

  • Title of items' details' list printed to user

  • Company/App name (logo name)

  • Logo fonts

  • Initial stock

  • Invoice numering

    image

LIVE APP

Access App HERE

REPOSITORY

Check out the repository HERE

AUTHOR

Edna Torres Munill

TABLE OF CONTENTS

HOW TO USE

CUSTOMER SIDE

From a user (customer) side, the app has been designed to be user-friendly and informs at all times of the actions that are being undertaken, or options that are available.

Python.Terminal.by.Code.Institute.-.Google.Chrome.2023-12-17.06-04-31.mp4
  1. After the logo and the welcome messages appear, click ENTER to access the Pricing List

  2. The Pricing List shows each item next to its price per unit

  3. You are then given the following options:

    1. Type any key or pres ENTER to create a new order : A new list is shown including each item's CODE (refer to next step 4)
    2. Type D (or d) to see items' details : The items' details are listed, each item with its details indented in a sub-list
    3. Type E (EXIT): You are then asked to confirm that you want to exit the app, and if confirmed, the logo shows with a copyright notice.
  4. You see the items list, each next to their unique item CODE

  5. You are asked to introduce the CODE related to the item you want to order (e.g.: A1)

  6. You are then asked 'How many 'Adult Day 1 Access' do you want to include to your order? (referring to the item related to the code given as an example)

  7. You input the number of the selected item to be included in your order (e.g.: 2)

  8. You get a notification stating "Added to your order: 2 'Adult Day 1 Access'"

  9. You are then given the following options:

    1. Type any key or press ENTER to continue order : Points 4 - 9 are repeated all over to add new item quantity to your order
    2. Type P to return to Pricing List : Shows pricing list and follows flow since above-mentioned step 2
    3. Type F to FINALIZE order
  10. Once you FINALIZE order, you are prompted to include your email, so that the invoice can be sent for due payment

  11. You are then asked to include a user name to include in your invoice

  12. The order is shown with the following information:

    1. Invoice number
    2. Invoice date
    3. User name
    4. User email
    5. Items ordered, showing each item's ordered units, and total price per items ordered
    6. Order's total amount
  13. You are asked review order, and you are given the following options:

    1. Type any key or press enter to CONFIRM order : Go to next step 14
    2. Type U to change email or user name : YOu are asked to type your email, then to type your user name (repeat from step 11 onwards)
    3. Type C to CONTINUE ORDERING : Shows Item list with correspondent CODES (repeat from step 4 onwards)
    4. Type E to EXIT the app : Cancels the order, and you are then asked to confirm that you want to exit the app, and uppon confirmation, the logo shows with a copyright notice.
  14. You are informed that the order has been confirmed, that an email has been sent, warns you that the order will be cancelled in case you fail to proceed to payment on due date.

  15. Confirms that email has been sent:

    image

SELLER SIDE

From the seller's side, this app is fully customizable to fit the seller's needs. Please refer to the README worksheet included in the SpreadSheet for more details:

image

  1. The following can be customized directly on the SpreadSheet, easily finding the customizable values as they are placed in cells with a green background: 1. App name (logo name) 2. Logo font 3. Welcome message (before, and after logo) 4. Items to sell 5. Price of items to sell 6. Item codes 7. Item details 8. Title of items details list printed to user 9. Inicial stock 10. Final 'copyright' message includes customizable logo name

  2. Every order generates an invoice, which is included in the last empty row of the invoices worksheet:

image

  1. The items sold are then included in the total_items_sold Worksheet:

image

  1. The remaining stock is updated through python code, and the initial stock can be manually updated to fit the seller tru stock per item:

image

  1. The revenue per item is also automatically calculated after each order through python code, as well as the grand total revenue, and updated to the total_sales Worksheet:

image

WATCH THIS VIDEO WHERE I HAVE CHANGED ALL CUSOTMIZABLE VALUES DIRECTLY ON THE SPREADSHEET TO CREATE A NEW CUSTOMIZED APP !!

  • Changed values in settings worksheet:

    image

  • Changed values in pricing worksheet:

    image

  • Changes values in item_details worksheet:

    image

  • WATCH THE MAGIC:

Python.Terminal.by.Code.Institute.-.Google.Chrome.2023-12-17.06-31-21.mp4
  • ALthough there were previous invoices generated with the original ROCK FEST settings, the items on the invoice have updated to match the items included on the Pricing Worksheet, so all is ready!:

    image

FEATURES

IMPLEMENTED FEATURES

This app contains the following features and functionalities:

  1. REUSABLE CODE : The most distinctive feature is that values are not hard-coded, and are all retrieved from the SpreadSheet, meaning that whoever wants to reuse the code, can easily customize the app to fit needs. These are the customizable app values: 1. App name (logo name) 2. Logo font 3. Welcome message (before, and after logo) 4. Items to sell 5. Price of items to sell 6. Item codes 7. Item details 8. Title of items details list printed to user 9. Inicial stock 10. Final 'copyright' message includes customizable logo name
Python.Terminal.by.Code.Institute.-.Google.Chrome.2023-12-17.06-31-21.mp4
  1. All data input by the user is trimmed, so any white space is dismissed
  2. When user is prompted to type a key, the input is case unsensitive, so whether the user includes upper case or lower case letters, it will not affect the flow.
  3. User can exit app anytime
  4. User is given several options, as for instance, to view item details' list or not
  5. User can return to pricing list at any time during the order
  6. User is informed at all times of each step, and its output
  7. Takes user's inputs (item to order, quantity, options after each step, email, user name, etc.)
  8. User can't type other than an integer from 1-30 as a quantity of item to be included in order, if not, receives ValueError
  9. Email validation (gives ValueError if user doesn't include valid format [email protected])
  10. Name validation (gives ValueError if input is left blank)
  11. Repeats ordering process as many times as the user demands, and updates order accordingly
  12. Sends email to user with all the order data
  13. Includes new invoice generated from order in 'invoice worksheet'
  14. Updates remaining stock in 'stock worksheet'
  15. Updates items sold in 'total_items_sold worksheet'
  16. Calculates total sales income per item after each order, and updates values in 'total_sales worksheet'
  17. Calculates grand total of sales, and updates value in 'total_sales worksheet'

FUTURE FEATURES

The following features are to be implemented in a near future:

  1. Create PDF using python, to be included in the email sent to the user, instead of writing the details of the order in the email body.
  2. Automatically cancel order if user does not proceed to payment on due date.

FLOW CHART

image

DATA MODEL

NEW_ORDER DICTIONARY

  1. After viewing Pricing List, when user selects option to Start, the invoice is generated by the generate_order() function. Updates NEW_ORDER dictionary with new invoice_no value, and current date:
# get key values to create NEW_ORDER dict
item_sales_new_order = invoices_worksheet.row_values(1)
# get mock values for each key to create NEW_ORDER dict
values_sales_new_order = invoices_worksheet.row_values(3)
# dict NEW_ORDER takes user inputs all along the app
# to create final invoice with total amount
NEW_ORDER = dict(zip(item_sales_new_order, values_sales_new_order))

def generate_order():
    """
    New order is generated.
    New sequencial invoice_no is generated from previous invoice no.
    in invoices_worksheet, and current date
    are included in NEW_ORDER dictionary
    """
    print_slow("Loading ...\n")
    # takes last invoice_no from invoices_worksheet;
    # default e.g.: INV-10000
    invoice = invoices_worksheet.col_values(1)[-1]
    # takes initial letter of last invoice_no
    # before the '-' e.g: INV
    invoice_letters = invoice.split("-")[0]
    # takes numbers of last invoice_no after 
    # the '-' and returns string e.g.: '10000'
    invoice_no = invoice.split("-")[1]
    # turns num string to integer,
    # and adds 1 to invoice_no; e.g.: 10001
    invoice_no = int(invoice_no) + 1
    # creates new invoice_no with same format 
    # (letters-nums) e.g. INV-10001
    invoice_no = f"{invoice_letters}-{invoice_no}"

    NEW_ORDER['invoice_no'] = invoice_no
    NEW_ORDER['order_date'] = DATE
    list_keyword_item()
    return NEW_ORDER

image

LIBRARIES USED

  • pyfiglet : To style logo in welcome message. Documentation taken from geeksforgeeks
  • google-auth : To give access to GoogleSheets API. Will use our creds.json file to set authentication for the project. Full documentation here.
  • gspread : To access and update data in SpreadSheet. Full documentation here
    • To install google-auth & gspread, type in terminal:
pip3 install gspread google-auth
  • To upgrade pip in future for newer versions, type in terminal:
python.exe -m pip install --upgrade pip
  • datetime : To get current date and time, for invoicing purposes. Full documentation here
  • sys : This module provides access to some variables used or maintained by the interpreter and to functions that interact strongly with the interpreter. Allows sensitible data stored in system variables stored in env.py to be accessed in our main run.py file. Full documentation here
  • os : This module provides a portable way of using operating system dependent functionality. Full documenttion here.
  • time : This module provides various time-related functions. Full documentation here
  • smtplib : This module defines an SMTP client session object that can be used to send mail to any internet machine with an SMTP or ESMTP listener daemon. Full documentation here
  • ssl : This module provides access to Transport Layer Security (often known as โ€œSecure Sockets Layerโ€) encryption and peer authentication facilities for network sockets, both client-side and server-side. This module uses the OpenSSL library. It is available on all modern Unix systems, Windows, macOS, and probably additional platforms, as long as OpenSSL is installed on that platform. Full documentation here
  • re : Regex module, to validate email input by user. Full documentation here
  • email.message : Import EmailMessage class from the email package, to send emails. Full documentation here

TESTING

This app has been carefully tested, as detailed below.

VALIDATION TESTING

CI Python Linter by Code Institute has been used to validate the code, and no errors were found:

image

MANUAL TESTING

  • User can exit app when given the oportunity all through the app (VIDEO 1 below)

  • User can view item details, and return to order (VIDEO 2 below)

  • User can view pricing list and return to order afterwards (VIDEO 2 below)

  • User gets ValueError if other that an item code is typed when requested to include an item code to order (VIDEO 3 below)

  • User gets ValueError if inputs other than an integer when requested to input the quantity of the selected item to order (VIDEO 3 below)

  • User can confinue ordering after including items in order (VIDEO 3 below)

  • If user types any space before or after the requested input, it does not give error, as it is trimmed (VIDEO 3 below)

  • User gets ValueError is other that an email format is typed when requested to include email address (VIDEO 3 below)

  • User gets ValueError if he accidentally or intentionally leaves the user name input blank whe requested to input a user name, must at least include a character (VIDEO 3 below)

  • User can change email address and user name after reviewing, in case an error was made while typing, without loosing the order (VIDEO 3 below)

  • User can continue ordering even after final order is printed on the terminal, and new items are added, or quantity updated.

  • Data successfully updates in all the Worksheets in the SpreadSheet (invoices, items_sold, stock, total_sales) (IMAGES 1,2,3,4 below)

  • User receives email (IMAGE 5, 6 below)

  • Email received contains subject (IMAGE 5, 6 below)

  • Email received contains sender (IMAGE 5, 6 below)

  • Email received contains the invoice data related to the user's order (IMAGE 6 below)

  • Email includes payment link (default link) (IMAGE 6 below)

  • VIDEO 1

Python.Terminal.by.Code.Institute.-.Google.Chrome.2023-12-17.06-45-27.mp4
  • VIDEO 2
Python.Terminal.by.Code.Institute.-.Google.Chrome.2023-12-17.06-59-33.mp4
  • VIDEO 3
Python.Terminal.by.Code.Institute.-.Google.Chrome.2023-12-17.07-12-18.mp4
  • IMAGES 1,2,3,4 - UPDATED WORKSHEETS

image

image

image

image

image

  • IMAGE 5, 6 - EMAIL

image

image

DEFECTS

DEFECTS TRACKING

I have created issues in GitHub in order to track the most relevant issues encountered, all successfully fixed:

image

DEFECTS OF NOTE

All the defects tracked as GitHub issues have been successfully fixed, and none remain.

OUTSTANDING DEFECTS

No outstanding defects have been found

DEPLOYMENT

PREREQUISITES

GOOGLE SHEETS TEMPLATE

This project has a Google Sheet linked to it: festival_tickets_sales.
As the project has been built in order to be as reusable as possible, you can make a copy of it:

image

After cloning the repository, updating the credentials (creds.json file), the env.py file with your own sensible data, and making sure the app is linked to your own Google account, you can update your copy made of the SpreadSheet to fit your needs.
IMPORTANT: Rename your copy exactly the same as it is inicually named - festival-tickets-sale
The SpreadSheet also contains a README Worksheet to remind you of the main instructions to avoid system breakdown, also reviewed in more detail below.

image

Find below the data included in each Worksheet, and which one can be to fit your needs:
IMPORTANT: You may ONLY change values that are in cells with a green background, but DO NOT change values in CELLS with a red background, to avoid system crash.

1. SETTINGS WORKSHEET

This Worksheet, as its name suggests includes general settings to be customized as follows:

  1. Logo/ company name
  2. Logo/ title font
  3. Welcome message before logo
  4. Welcome message after logo
  5. Title of the item details (if you have some items that have extra detail info, suck as packs or bonus, here you can update the title the user will see when the user chooses to access the item details)

image

2. PRICING WORKSHEET

This Worksheet, as its name suggests, includes a list of the items to be sold, and their related values, as follows:

  1. ITEM TYPE: You can change the type of items you are selling. E.g.: If you are selling lesson packs, you should change TICKETS by PACKS.
  2. ITEM NAMES: Update the names of the items you are selling. E.g.: 10 lessons pack instead of Adult Day 1 Access, and so on with each item.
  3. PRICE: Change the prices of each item. IMPORTANT: Use a dot '.' for decimal values, NOT COMMAS, as the app system does not recognize commas for decimals.
  4. CODE: Each item has to have a unique code that will be displayed next to the item in a list. The user will have to type the code of the item to be included in the order. It is recommended to include 2 value codes to make it easy for the user to type the desired item's code.

image

3. ITEM DETAILS WORKSHEET

This Worksheet is meant to include the items' details to be shown to the user when the user requests to see items' details after the pricing list os displayed:

image

IMPORTANT: You MUST include at least one item with at least one 'extra_info' to avoid system crash.
You can customize the following:

image

  1. item_type: For your own record, as this will not be displayed to the client (app user)
  2. item_display_name: This will be displayed to the client, and shouldbe the same af the item name introduced in the pricing worksheet.
  3. extra_info: You can include until 4 different features for each item, each if which will be displayed to the client that requests to see details as the example below:

image

4. INVOICES WORKSHEET

This Worksheet, as its name suggests, shows all the invoices (orders), and should NOT be updated, unless when you make a coy of the SpreadSheet, or if a customer cancels an order. The item names are automatically retrieved from the Pricing Worksheet, and Total Amount is also automatically calculated also with the prices included in the Pricing Worksheet. The only data to be updated before your first invoice is generated id the original dafault invoice value INV-100000 placed in a cell with a green background. All other values placed in cells with red background should not be changed to avoid system breakdown.
IMPORTANT: Your default invoice should contain the following format : letter(s)-nums (at least 1 letter BEFORE a mandatory - , and then as many 0 as your invoice numbering system requires.

In the following screenshot, you can see two test invoices created:

image

5. TOTAL ITEMS SOLD WORKSHEET

As its name suggests, this Worksheet shows how many items have been sold (by item type). The amount is automatically calculated by the code, by summing each item type from all orders, and the item names are also automatically retrieved from the pricing worksheet, so NO NEED TO MANUALLY UPDATE ANYTHING. Find an example below:

image

6. STOCK WORKSHEET

As its name suggests, this Worksheet shows the remaining stock per item type. The item names are automatically retrieved from the Pricing Worksheet, and the total remaining stock per item is automatically calculated every time the code is run. The only values to be updated are to INITIAL STOCK per item, values in cells with a green background, from which the sold items will be sustracted.
IMPORTANT: The row of 'REMAINING STOCK' should also manually be set only the 1st time, to match the initial stock values, and then it will be automatically updated after each sale.

image

7. TOTAL SALES WORKSHEET

As its name suggests, this Worksheet shows the total sales per item, as well as the total income generated by selling each and every item. The item names are retrieved from the Princing Worksheet, and the total amounts automatically calculated, so it shouldn't be updated manually. See an example below:

image

GMAIL ACCOUNT WITH API KEY

  • Create a gmail account
  • WITHOUT 2-STEP AUTENTICATION : Once you are signed in you need to make sure it has less secure app access turned on use this link
  • WITH 2-STEP AUTENTICATION : These accounts require an application-specific password for less secure apps access. To get your specific app password, follow these steps:
    1. Go to your Google Account.
    2. Select Security.
    3. Under "Signing in to Google," select 2-Step Verification.
    4. At the bottom of the page, select App passwords.
    5. Enter a name that helps you remember where youโ€™ll use the app password.
    6. Select Generate.
    7. To enter the app password, follow the instructions on your screen.
    8. The app password is the 16-character code that generates on your device.
    9. Select Done.
    10. IMPORTANT NOTE: The app password that you've generated is a sensitive data, so you must store it in an env.py. Follow the steps stated here:

CREATE PROJECT IN GOOGLE CLOUD PLATFORM

image

ENABLE APIs

Enable the following APIs for this project:

  • Google Drive API
  • Google Sheets API

1. ENABLE GOOGLE DRIVE API:

  1. On the project page, to enable APIs and services: Click on 'more products' dropdown, and select 'APIs and Services', then 'Library', and type 'Google Drive API' on the search bar, and enable it.

image

image

image

  1. Create 'Credentials': After clicking on 'Enable' in the previous step, you are taken to the API Overview page, where we click on 'Create Credentials': image

  2. On the credentials form, select 'Application Data' for the question 'What data will you be accessing?', then click 'Next':

    image

  3. Then, on the next stage of the form, include a 'Service account name'. An account email will be automatically generated following your input. Then, click 'Create and Continue':

    image

  4. In the 'Role' Dropdown box choose Basic > Editor then press Continue:

    image

    image

  5. Other settings are optional, so click on 'Done':

    image

  6. On the 'Credentials' page, the account generated will appear at the bottom of the page. Click on it to open account page:

    image

  7. Once in the account page, click on 'Keys':

    image

  8. Click on the 'Add Key' dropdown and select 'Create New Key'.

  9. Select JSON option. Once you click on 'Create', a file will automatically download to your 'downsloaded' folder on your device. This file will normally be downloaded to your 'downloads' folder, and will typically be named as your project name, being a .json type document:

    image

2. ENABLE GOOGLE SHEETS API :

  • Go to 'APIs and Services' > 'Library' and type 'Google Sheets API' on the search bar. Click on it, and 'Enable'. No need to give credentials again, as the credentials given to Google Drive include Google Sheets:
    image

CONNECT TO APIs THROUGH PYTHON

  • Include the SCOPE constant variable to the run.py file (no need to change it when reusing the code, just leave it as it is):
SCOPE = [
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/drive"
    ]
  • The following constant variables allows the code to access our SpreadSheet:
# CREDS constant variable, takes creds from file creds.json
# Allows code to access SpreadSheet
CREDS = Credentials.from_service_account_file('creds.json')
SCOPED_CREDS = CREDS.with_scopes(SCOPE)
GSPREAD_CLIENT = gspread.authorize(SCOPED_CREDS)
SHEET = GSPREAD_CLIENT.open('festival_tickets_sale')

DEPLOY LOCALLY IN YOUR IDE

INCLUDE GOOGLE CLOUD CREDENTIALS IN PROJECT

  1. Copy .json credential file previously downloaded from Google Cloud Platform to our project folder, and rename it as 'creds.json' for simplicity sake.
  • Your creds.json file including your credentials should look like that:
{
    "type": "service_account",
    "project_id": "<YOUR_VALUE>",
    "private_key_id": "<YOUR_VALUE>",
    "private_key": "<YOUR_VALUE>",
    "client_email": "<YOUR_VALUE>",
    "client_id": "<YOUR_VALUE>",
    "auth_uri": "https://accoutns.google.com/0/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cer_url": "https://www.googleapis.com/oauth2/v1/certs",
    "clien_x509_cert_url": "<YOUR_VALUE>"
}

DEPLOY LOCALLY IN YOUR IDE

SECRETS

IMPORTANT: Avoid secrets from being uploaded to GitHub, open .gitignore file in project, and insure to include creds.json and env.py Don't forget to CTR+S:

image

creds.json

This file holds the secrets to have access to the google drive and sheet you created in prerequisites.

  1. Copy the file that you downloaded from Google Cloud Platform, and rename it as 'creds.json' and load it to your main directory in your IDE.
  2. BEFORE COMMITTING TO GITHUB : On the terminal, type 'git add .', then 'git status' and make sure the creds.json file is not in the list. Once you are reassured that it is not in the list to be committed, commit.

env.py

This file holds the access to the email you created in prerequisites so the program can send confirmation emails to users.

  1. Create an env.py file
  2. Include the follwoing code:
import os
from pathlib import Path
  1. Use the following method to store your sensitive data into system variables:
os.environ.setdefault('EMAIL_APP_PASS', 'your_own_app_password')
os.environ.setdefault('APP_EMAIL', 'your_own_google_account_email')
  1. Include the env.py file in your .gitignore file to avoid pushing it to GitHub revealing your secret data.
  2. Import Operational System to your run.py file so it can access the system variables secretely stored in your env.py file:
import os
  1. To access the system variables in your run.py file, use the following method, and store them in other variables:
sender = os.environ.get("APP_EMAIL")
gmail_app_password = os.environ.get("EMAIL_APP_PASS")
  1. BEFORE COMMITTING TO GITHUB : On the terminal, type 'git add .', then 'git status' and make sure the env.py file is not in the list. Once you are reassured that it is not in the list to be committed, commit.

INSTALL REQUIREMENTS.TXT

Before deploying the app, the requirements.txt file needs to be executed to get the dependencies installed. On the terminal, type:

pip3 install -r requirements.txt
  • In case you install further modules or libraries, then the requirements.txt file must be updated by typing in the terminal the following command:
pip3 freeze > requirements.txt

RUN THE SERVER

to run locally, type on the terminal:

DEPLOY IN HEROKU

Set up new Heroku app

ENVIRONMENT VARIABLES

Go to 'Settings' to store the environmental variables, and click on 'Config Vars':

image

Add the following variables:

  • APP_MAIL : Your app email
  • EMAIL_APP_PASS : Your app password
  • CREDS : creds.json (all data, including the {})
  • PORT : 8000

DEPLOYMNET METHOD

  • Click the deploy tab
  • Scroll down and select Github
  • Use the github link and type in the name of your repository
  • Click from deploy from branch and select main
  • Once your application is running, switch to Automatic so that any changes are automatically reflecte in Heroku deployed app

DEPLOY IN HEROKU

CREDITS

The app was coded using Code Institute's P3 Template, which includes all necessary features and files for it to run smoothly on Heroku, by creating a terminal, as this project does not have any front-end code.

ACKNOWLEDGEMENTS

festival-tickets-sale's People

Contributors

ethra8 avatar

Watchers

 avatar

festival-tickets-sale's Issues

Email validation

User can input anything which does not have an email format, and code accepts it

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.