/** * Common.hx : Shared entities between server and client */ @:keep typedef OrderSimple = { products: Array<{ product:ProductInfo, quantity:Int }>, total:Float } //A temporary order, waiting for being paid and definitely recorded. @:keep typedef OrderInSession = { products:Array <{ productId:Int, quantity:Float, #if !js ?product:db.Product, ?distributionId:Int, #end } > , ?userId:Int, total:Float, //price to pay ?paymentOp:Int, //payment operation ID } @:keep typedef ProductInfo = { id : Int, name : String, ref : Null, image : Null, contractId : Int, price : Float, vat : Null, //VAT rate vatValue : Null, //amount of VAT included in the price contractTax : Null, //pourcentage de commission défini dans le contrat contractTaxName : Null, //label pour la commission : ex: "frais divers" desc : Null, categories : Null>, //used in old shop subcategories : Null>, //used in new shop orderable : Bool, //can be currently ordered stock: Null, //available stock hasFloatQt : Bool, qt:Null, unitType:Null, organic:Bool, variablePrice:Bool, wholesale:Bool, active:Bool, ?distributionId:Null, //in the context of a distrib } @:keep typedef ProductWithQuantity = { product: ProductInfo, quantity: Int } enum Unit{ Piece; Kilogram; Gram; Litre; Centilitre; } typedef CategoryInfo = { id:Int, name:String, ?subcategories:Array } /** * datas used with the "tagger" ajax class */ @:keep typedef TaggerInfos = { products:Array<{product:ProductInfo,categories:Array}>,//tagged products categories : Array<{id:Int,categoryGroupName:String,color:String,tags:Array<{id:Int,name:String}>}>, //groupe de categories + tags } /** * Links in navbars for plugins */ typedef Link = { id:String, link:String, name:String, ?icon:String, } typedef Block = { id:String, title:String, ?icon:String, html:String } typedef UserOrder = { id:Int, userId:Int, userName:String, ?userEmail : String, ?userId2:Int, ?userName2:String, ?userEmail2:String, //deprecated ?productId:Int, ?productRef:String, ?productName:String, ?productPrice:Float, ?productImage:String, ?productQt:Float, ?productUnit:Unit, ?productHasFloatQt:Bool, ?productHasVariablePrice:Bool, //new way ?product:ProductInfo, quantity:Float, smartQt:String, subTotal:Float, fees:Null, percentageName:Null, percentageValue:Null, total:Float, //flags paid:Bool, invertSharedOrder:Bool, canceled:Bool, canModify:Bool, contractId:Int, contractName:String, } typedef PlaceInfos = { id:Int, name:String, address1:String, address2:String, zipCode:String, city:String, latitude:Float, longitude:Float } typedef UserInfo = { id:Int, name:String, email:String, } typedef GroupOnMap = { id:Int, name:String, image:String, place:PlaceInfos, } enum OrderFlags { InvertSharedOrder; //invert order when there is a shared/alternated order //Canceled; //flag for cancelled orders, qt should always be 0 } typedef OrderByProduct = { quantity:Float, smartQt:String, pid:Int, pname:String, ref:String, priceHT:Float, priceTTC:Float, vat:Float, totalHT:Float, totalTTC:Float, weightOrVolume:String, }; typedef OrderByEndDate = {date: String,contracts: Array}; /** Event enum used for plugins. As in most CMS event systems, the events (or "triggers") can be caught by plugins to perform an action or modifiy data carried by the event. **/ enum Event { Page(uri:String); //a page is displayed Nav(nav:Array, name:String, ?id:Int); //a navigation is displayed, optionnal object id if needed Blocks(blocks:Array, name:String, ?context:Dynamic); //HTML blocks that can be displayed on a page #if sys SendEmail(message : sugoi.mail.Mail); //an email is sent NewMember(user:db.User,group:db.Amap); //a new member is added to a group NewGroup(group:db.Amap, author:db.User); //a new group is created //Distributions PreNewDistrib(contract:db.Contract); //when displaying the insert distribution form NewDistrib(distrib:db.Distribution); //when a new distrinbution is created PreEditDistrib(distrib:db.Distribution); EditDistrib(distrib:db.Distribution); DeleteDistrib(distrib:db.Distribution); PreNewDistribCycle(cycle:db.DistributionCycle); NewDistribCycle(cycle:db.DistributionCycle); MultiDistribEvent(md:MultiDistrib); //Products PreNewProduct(contract:db.Contract); //when displaying the insert distribution form NewProduct(product:db.Product); //when a new product is created PreEditProduct(product:db.Product); EditProduct(product:db.Product); DeleteProduct(product:db.Product); BatchEnableProducts(data:{pids:Array,enable:Bool}); ProductInfosEvent(p:ProductInfo,?d:db.Distribution); //when infos about a product are displayed //Contracts EditContract(contract:db.Contract,form:sugoi.form.Form); DuplicateContract(contract:db.Contract); DeleteContract(contract:db.Contract); //crons DailyCron; HourlyCron; MinutelyCron; //orders MakeOrder(orders:Array); StockMove(order:{product:db.Product, move:Float}); //when a stock is modified //payments GetPaymentTypes(data:{types:Array}); NewOperation(op:db.Operation); #end } /* * Product Taxonomy structure */ typedef TxpDictionnary = { products:Map, categories:Map, subCategories:Map, } /* * Tutorials */ enum TutoAction { TAPage(uri:String); TANext; } enum TutoPlacement { TPTop; TPBottom; TPLeft; TPRight; } class TutoDatas { public static var TUTOS; #if js //async public static function get(tuto:String, callback:Dynamic->Void){ #if !test sugoi.i18n.Locale.init(App.instance.LANG, function(t:sugoi.i18n.GetText){ App.instance.t = t; init(t); var tuto = TUTOS.get(tuto); callback(tuto); }); #end } #else //sync public static function get(tuto:String):{name:String, steps:Array<{element:String,text:String,action:TutoAction,placement:TutoPlacement}>} { sugoi.i18n.Locale.init(App.current.getLang()); init(sugoi.i18n.Locale.texts); return TUTOS.get(tuto); } #end static function init(t:sugoi.i18n.GetText){ TUTOS = [ "intro" => { name:t._("Guided tour for the coordinator"), steps:[ { element:null, text:t._("

In order to better discover Cagette.net, we propose to do a guided tour of the user interface of the software.
You will then have a global overview on the different tools that are available to you.

You will be able to stop and start again this tutorial whenever you want.

"), action: TANext, placement : null }, { element:"ul.nav.navbar-left", text:t._( "This part of the navigation bar is visible by all members.
It allows to access to the three main pages:
  • The home page which displays orders and the delivery planning.
  • On the My account page, you can update your personal information and check your orders history
  • On the Farmers page, you can see all farmers and coordinators of the group
"), action: TANext, placement : TPBottom }, { element:"ul.nav.navbar-right", text:t._("This part is for coordinators only.Here you will be able to manage the register of members, orders, products, etc.

Now click on the Members section

"), action: TAPage("/member"), placement : TPBottom },{ element:".article .table td:first", text:t._("The purpose of this section is to administrate the list of your members.
Every time that you register a new membrer, an account will be created for him/her. Now the member can join you at Cagette.net and order or consult the planning of the deliveries.

Now click on a member in the list

"), action: TAPage("/member/view/*"), placement : TPRight },{ element:".article:first", text:t._("This is the page of a member. Here you can :
  • see and change their contact details
  • manage the membership fee of your group
  • see a summary of their orders
"), action: TANext, placement : TPRight },{ element:"ul.nav #contractadmin", text:t._("Now let's have a look at the contracts section which is very important for coordinators."), action: TAPage("/contractAdmin"), placement : TPBottom },{ element:"#contracts", text:t._("Here you find the list of contracts.They inculde a start date, a end date, and represent your relationship with a farmer.

Here you can manage :

  • the list of products of this farmer
  • the orders of members for this farmer
  • and plan the delivery schedule

"), action: TANext, placement : TPBottom },{ element:"#places", text:t._("Here you can manage the list of delivery places.
Don't forget to key-in the complete address as a map will be displayed based on this address"), action: TANext, placement : TPTop },{ element:"#contracts table .btn:first", text:t._("Let's look closer at how to manage a contract. Click on this button"), action: TAPage("/contractAdmin/view/*"), placement : TPBottom },{ element:".table.table-bordered:first", text:t._("Here is a summary of the contract.
There are two types of contracts:
  • Constant contracts: the member commits on buying the same products during the whole duration of the contract
  • Variable contracts: the member can choose what he buys for each delivery.
"), action: TANext, placement : TPRight },{ element:"#subnav #products", text:t._("Let's see now the page Products"), action : TAPage("/contractAdmin/products/*"), placement:TPRight },{ element:".article .table", text:t._("On this page, you can manage the list of products offered by this supplier.
Define at least the name and the price of products. It is also possible to add a description and a picture."), action: TANext, placement : TPTop },{ element:"#subnav #deliveries", text:t._("Let's see the deliveries page"), action : TAPage("/contractAdmin/distributions/*"), placement:TPRight },{ element:".article .table", text:t._("Here we can manage the list of deliveries for this supplier.
In the software, a delivery has a date, a start time, and an end time. The location of the delivery must also be defined, by using the list that we have already seen."), action: TANext, placement : TPLeft },{ element:"#subnav #orders", text:t._("Let's see now the Orders page"), action : TAPage("/contractAdmin/orders/*"), //can fail if the contract is variable because the uri is different placement:TPRight },{ element:".article .table", text:t._("Here we can manage the list of orders for this supplier.
If you choose to \"open orders\" to members, they will be able to make their orders online themselves.
This page will centralize automatically the orders for this supplier. Otherwise, as a coordinator, you will be able to enter orders on behalf of a member."), action: TANext, placement : TPLeft },{ element:"ul.nav #messages", text:t._("

We have seen the main features related to contracts.

Let's see the messaging section.

"), action: TAPage("/messages"), placement : TPBottom },{ element:null, text:t._("

The messaging section allows you to send e-mails to different lists of members. It is not necessary anymore to maintain a lot of lists of e-mails depending on contracts, as all these lists are automatically generated.

E-mails are sent with your e-mail address as sender, so you will receive answers in your own mailbox.

"), action: TANext, placement : null },{ element:"ul.nav #amapadmin", text:t._("Click here now on this page"), action : TAPage("/amapadmin"), placement : TPBottom, },{ element:"#subnav", text:t._("

In this last page, you can configure everything that is related to your group.

The page Access rights is important as it is where you can define other coordinators among members. They will then be able to manage one or many contracts, send emails, etc.

"), action:TANext, placement : TPBottom },{ element:"#footer", text:t._("

This is the last step of this tutorial. I hope that it gave you a good overview of this software.
To go further, do not hesitate to look at the documentation. The link is always available at the bottom of the screen.

"), action:TANext, placement : TPBottom } ] }, ]; } } /** * Order Reports */ enum OrdersReportGroupOption{ ByMember; ByProduct; } enum OrdersReportFormatOption{ Table; Csv; PrintableList; //list de distrib ? } //Report Options : should be usable in an URL, an API call... typedef OrdersReportOptions = { //time scope startDate:Date, endDate:Date, //formatting ?groupBy:OrdersReportGroupOption, //group order by... ?format:OrdersReportFormatOption, //table , csv ? //filters : ?groups:Array, ?contracts:Array, //which contracts ?distributions:Array, }